<!DOCTYPE html><html class=split lang=en-US-x-hixie><script src=../link-fixup.js defer=""></script>
<!-- Mirrored from html.spec.whatwg.org/dev/custom-elements.html by HTTrack Website Copier/3.x [XR&CO'2014], Wed, 10 Sep 2025 08:36:28 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=utf-8" /><!-- /Added by HTTrack -->
<meta charset=utf-8><meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name=viewport><title>HTML Standard, Edition for Web Developers</title><meta content=#3c790a name=theme-color><meta content="light dark" name=color-scheme><link rel=stylesheet href=../../resources.whatwg.org/standard-shared-with-dev.css crossorigin=""><link rel=icon href=https://resources.whatwg.org/logo.svg crossorigin=""><link rel=stylesheet href=styles.css crossorigin=""><script>
   function toggleStatus(div) {
     div.parentNode.classList.toggle('wrapped');
   }
   function setLinkFragment(link) {
     link.hash = location.hash;
   }
  </script><body>
  <script async="" src=search.js></script>
  
  
  <header id=head class="head with-buttons">
   <a href=https://whatwg.org/ class=logo><img width=100 alt=WHATWG crossorigin="" class=darkmode-aware src=https://resources.whatwg.org/logo.svg height=100></a>
   
   <hgroup><h1><a rel=home href=index.html>HTML: The Living Standard</a></h1><p id=dev-edition-h2>Edition for Web Developers — Last Updated <span class=pubdate>10 September 2025</span></hgroup>
   

   <div id=search>
    <input placeholder="Search. Press '/'" autocomplete=off name=query id=query type=search>
    <ol id=results></ol>
   </div>
  </header>

  

  

  

  
  

  
  

  

  <nav><a href=canvas.html>← 4.12.5 The canvas element</a> — <a href=index.html>Table of Contents</a> — <a href=semantics-other.html>4.14 Common idioms without dedicated elements →</a></nav><ol class=toc><li><ol><li><a href=custom-elements.html#custom-elements><span class=secno>4.13</span> Custom elements</a><ol><li><a href=custom-elements.html#custom-elements-intro><span class=secno>4.13.1</span> Introduction</a><ol><li><a href=custom-elements.html#custom-elements-autonomous-example><span class=secno>4.13.1.1</span> Creating an autonomous custom element</a><li><a href=custom-elements.html#custom-elements-face-example><span class=secno>4.13.1.2</span> Creating a form-associated custom element</a><li><a href=custom-elements.html#custom-elements-accessibility-example><span class=secno>4.13.1.3</span> Creating a custom element with default accessible roles, states, and properties</a><li><a href=custom-elements.html#custom-elements-customized-builtin-example><span class=secno>4.13.1.4</span> Creating a customized built-in element</a><li><a href=custom-elements.html#custom-elements-autonomous-drawbacks><span class=secno>4.13.1.5</span> Drawbacks of autonomous custom elements</a><li><a href=custom-elements.html#custom-elements-upgrades-examples><span class=secno>4.13.1.6</span> Upgrading elements after their creation</a><li><a href=custom-elements.html#scoped-custom-element-registries><span class=secno>4.13.1.7</span> Scoped custom element registries</a><li><a href=custom-elements.html#exposing-custom-element-states><span class=secno>4.13.1.8</span> Exposing custom element states</a></ol><li><a href=custom-elements.html#custom-element-conformance><span class=secno>4.13.2</span> Requirements for custom element constructors and
  reactions</a><ol><li><a href=custom-elements.html#preserving-custom-element-state-when-moved><span class=secno>4.13.2.1</span> Preserving custom element state when moved</a></ol><li><a href=custom-elements.html#custom-elements-core-concepts><span class=secno>4.13.3</span> Core concepts</a><li><a href=custom-elements.html#custom-elements-api><span class=secno>4.13.4</span> The <code>CustomElementRegistry</code> interface</a><li><a href=custom-elements.html#custom-element-reactions><span class=secno>4.13.5</span> Custom element reactions</a><li><a href=custom-elements.html#element-internals><span class=secno>4.13.6</span> Element internals</a><ol><li><a href=custom-elements.html#shadow-root-access><span class=secno>4.13.6.1</span> Shadow root access</a><li><a href=custom-elements.html#form-associated-custom-elements><span class=secno>4.13.6.2</span> Form-associated custom elements</a><li><a href=custom-elements.html#accessibility-semantics><span class=secno>4.13.6.3</span> Accessibility semantics</a><li><a href=custom-elements.html#custom-state-pseudo-class><span class=secno>4.13.6.4</span> Custom state pseudo-class</a></ol></ol></ol></ol><h3 id=custom-elements><span class=secno>4.13</span> Custom elements<a href=#custom-elements class=self-link></a></h3><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements title="One of the key features of the Web Components standard is the ability to create custom elements that encapsulate your functionality on an HTML page, rather than having to make do with a long, nested batch of elements that together provide a custom page feature. This article introduces the use of the Custom Elements API.">Using_custom_elements</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>63+</span></span><span class="safari yes"><span>Safari</span><span>10.1+</span></span><span class="chrome yes"><span>Chrome</span><span>54+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div>

  <h4 id=custom-elements-intro><span class=secno>4.13.1</span> Introduction<a href=#custom-elements-intro class=self-link></a></h4>

  

  <p><a href=#custom-element id=custom-elements-intro:custom-element>Custom elements</a> provide a way for authors to build their
  own fully-featured DOM elements. Although authors could always use non-standard elements in their
  documents, with application-specific behavior added after the fact by scripting or similar, such
  elements have historically been non-conforming and not very functional. By <a href=#element-definition id=custom-elements-intro:element-definition>defining</a> a custom element, authors can inform the parser how to
  properly construct an element and how elements of that class should react to changes.</p>

  <p>Custom elements are part of a larger effort to "rationalise the platform", by explaining
  existing platform features (like the elements of HTML) in terms of lower-level author-exposed
  extensibility points (like custom element definition). Although today there are many limitations
  on the capabilities of custom elements—both functionally and semantically—that prevent them from
  fully explaining the behaviors of HTML's existing elements, we hope to shrink this gap over
  time.</p>

  <h5 id=custom-elements-autonomous-example><span class=secno>4.13.1.1</span> Creating an autonomous custom element<a href=#custom-elements-autonomous-example class=self-link></a></h5>

  

  <p>For the purposes of illustrating how to create an <a href=#autonomous-custom-element id=custom-elements-autonomous-example:autonomous-custom-element>autonomous custom element</a>, let's
  define a custom element that encapsulates rendering a small icon for a country flag. Our goal is
  to be able to use it like so:</p>

  <pre><code class='html'><c- p>&lt;</c-><c- f>flag-icon</c-> <c- e>country</c-><c- o>=</c-><c- s>&quot;nl&quot;</c-><c- p>&gt;&lt;/</c-><c- f>flag-icon</c-><c- p>&gt;</c-></code></pre>

  <p>To do this, we first declare a class for the custom element, extending
  <code>HTMLElement</code>:</p>

  <pre><code class='js'><c- a>class</c-> FlagIcon <c- k>extends</c-> HTMLElement <c- p>{</c->
  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_countryCode <c- o>=</c-> <c- kc>null</c-><c- p>;</c->
  <c- p>}</c->

  <c- k>static</c-> observedAttributes <c- o>=</c-> <c- p>[</c-><c- u>&quot;country&quot;</c-><c- p>];</c->

  attributeChangedCallback<c- p>(</c->name<c- p>,</c-> oldValue<c- p>,</c-> newValue<c- p>)</c-> <c- p>{</c->
    <c- c1>// name will always be &quot;country&quot; due to observedAttributes</c->
    <c- k>this</c-><c- p>.</c->_countryCode <c- o>=</c-> newValue<c- p>;</c->
    <c- k>this</c-><c- p>.</c->_updateRendering<c- p>();</c->
  <c- p>}</c->
  connectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->_updateRendering<c- p>();</c->
  <c- p>}</c->

  get country<c- p>()</c-> <c- p>{</c->
    <c- k>return</c-> <c- k>this</c-><c- p>.</c->_countryCode<c- p>;</c->
  <c- p>}</c->
  set country<c- p>(</c->v<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->setAttribute<c- p>(</c-><c- u>&quot;country&quot;</c-><c- p>,</c-> v<c- p>);</c->
  <c- p>}</c->

  _updateRendering<c- p>()</c-> <c- p>{</c->
    <c- c1>// Left as an exercise for the reader. But, you&apos;ll probably want to</c->
    <c- c1>// check this.ownerDocument.defaultView to see if we&apos;ve been</c->
    <c- c1>// inserted into a document with a browsing context, and avoid</c->
    <c- c1>// doing any work if not.</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

  <p>We then need to use this class to define the element:</p>

  <pre><code class='js'>customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;flag-icon&quot;</c-><c- p>,</c-> FlagIcon<c- p>);</c-></code></pre>

  <p>At this point, our above code will work! The parser, whenever it sees the <code>flag-icon</code> tag, will construct a new instance of our <code>FlagIcon</code> class, and tell our code about its new <code>country</code>
  attribute, which we then use to set the element's internal state and update its rendering (when
  appropriate).</p>

  <p>You can also create <code>flag-icon</code> elements using the DOM API:</p>

  <pre><code class='js'><c- a>const</c-> flagIcon <c- o>=</c-> document<c- p>.</c->createElement<c- p>(</c-><c- u>&quot;flag-icon&quot;</c-><c- p>)</c->
flagIcon<c- p>.</c->country <c- o>=</c-> <c- u>&quot;jp&quot;</c->
document<c- p>.</c->body<c- p>.</c->appendChild<c- p>(</c->flagIcon<c- p>)</c-></code></pre>

  <p>Finally, we can also use the <a href=#custom-element-constructor id=custom-elements-autonomous-example:custom-element-constructor>custom element constructor</a> itself. That is, the above
  code is equivalent to:</p>

  <pre><code class='js'><c- a>const</c-> flagIcon <c- o>=</c-> <c- k>new</c-> FlagIcon<c- p>()</c->
flagIcon<c- p>.</c->country <c- o>=</c-> <c- u>&quot;jp&quot;</c->
document<c- p>.</c->body<c- p>.</c->appendChild<c- p>(</c->flagIcon<c- p>)</c-></code></pre>

  <h5 id=custom-elements-face-example><span class=secno>4.13.1.2</span> Creating a form-associated custom element<a href=#custom-elements-face-example class=self-link></a></h5>

  

  <p>Adding a static <code>formAssociated</code> property, with a true value, makes an
  <a href=#autonomous-custom-element id=custom-elements-face-example:autonomous-custom-element>autonomous custom element</a> a <a href=#form-associated-custom-element id=custom-elements-face-example:form-associated-custom-element>form-associated custom element</a>. The
  <code>ElementInternals</code> interface helps you to implement functions and properties common
  to form control elements.</p>

  <pre><code class='js'><c- a>class</c-> MyCheckbox <c- k>extends</c-> HTMLElement <c- p>{</c->
  <c- k>static</c-> formAssociated <c- o>=</c-> <c- kc>true</c-><c- p>;</c->
  <c- k>static</c-> observedAttributes <c- o>=</c-> <c- p>[</c-><c- t>&apos;checked&apos;</c-><c- p>];</c->

  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachInternals<c- p>();</c->
    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;click&apos;</c-><c- p>,</c-> <c- k>this</c-><c- p>.</c->_onClick<c- p>.</c->bind<c- p>(</c-><c- k>this</c-><c- p>));</c->
  <c- p>}</c->

  get form<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->form<c- p>;</c-> <c- p>}</c->
  get name<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->getAttribute<c- p>(</c-><c- t>&apos;name&apos;</c-><c- p>);</c-> <c- p>}</c->
  get type<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->localName<c- p>;</c-> <c- p>}</c->

  get checked<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->hasAttribute<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>);</c-> <c- p>}</c->
  set checked<c- p>(</c->flag<c- p>)</c-> <c- p>{</c-> <c- k>this</c-><c- p>.</c->toggleAttribute<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>,</c-> Boolean<c- p>(</c->flag<c- p>));</c-> <c- p>}</c->

  attributeChangedCallback<c- p>(</c->name<c- p>,</c-> oldValue<c- p>,</c-> newValue<c- p>)</c-> <c- p>{</c->
    <c- c1>// name will always be &quot;checked&quot; due to observedAttributes</c->
    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->setFormValue<c- p>(</c-><c- k>this</c-><c- p>.</c->checked <c- o>?</c-> <c- t>&apos;on&apos;</c-> <c- o>:</c-> <c- kc>null</c-><c- p>);</c->
  <c- p>}</c->

  _onClick<c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->checked <c- o>=</c-> <c- o>!</c-><c- k>this</c-><c- p>.</c->checked<c- p>;</c->
  <c- p>}</c->
<c- p>}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- t>&apos;my-checkbox&apos;</c-><c- p>,</c-> MyCheckbox<c- p>);</c-></code></pre>

  <p>You can use the custom element <code>my-checkbox</code> like a built-in
  form-associated element. For example, putting it in <code id=custom-elements-face-example:the-form-element><a href=forms.html#the-form-element>form</a></code> or <code id=custom-elements-face-example:the-label-element><a href=forms.html#the-label-element>label</a></code>
  associates the <code>my-checkbox</code> element with them, and submitting the
  <code id=custom-elements-face-example:the-form-element-2><a href=forms.html#the-form-element>form</a></code> will send data provided by <code>my-checkbox</code> implementation.
  </p>

  <pre><code class='html'><c- p>&lt;</c-><c- f>form</c-> <c- e>action</c-><c- o>=</c-><c- s>&quot;...&quot;</c-> <c- e>method</c-><c- o>=</c-><c- s>&quot;...&quot;</c-><c- p>&gt;</c->
  <c- p>&lt;</c-><c- f>label</c-><c- p>&gt;&lt;</c-><c- f>my-checkbox</c-> <c- e>name</c-><c- o>=</c-><c- s>&quot;agreed&quot;</c-><c- p>&gt;&lt;/</c-><c- f>my-checkbox</c-><c- p>&gt;</c-> I read the agreement.<c- p>&lt;/</c-><c- f>label</c-><c- p>&gt;</c->
  <c- p>&lt;</c-><c- f>input</c-> <c- e>type</c-><c- o>=</c-><c- s>&quot;submit&quot;</c-><c- p>&gt;</c->
<c- p>&lt;/</c-><c- f>form</c-><c- p>&gt;</c->
</code></pre>

  <h5 id=custom-elements-accessibility-example><span class=secno>4.13.1.3</span> Creating a custom element with default accessible roles, states, and properties<a href=#custom-elements-accessibility-example class=self-link></a></h5>

  

  <p>By using the appropriate properties of <code>ElementInternals</code>, your custom element can
  have default accessibility semantics. The following code expands our form-associated checkbox from
  the previous section to properly set its default role and checkedness, as viewed by accessibility
  technology:</p>

  <pre><code class='js'><c- a>class</c-> MyCheckbox <c- k>extends</c-> HTMLElement <c- p>{</c->
  <c- k>static</c-> formAssociated <c- o>=</c-> <c- kc>true</c-><c- p>;</c->
  <c- k>static</c-> observedAttributes <c- o>=</c-> <c- p>[</c-><c- t>&apos;checked&apos;</c-><c- p>];</c->

  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachInternals<c- p>();</c->
    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;click&apos;</c-><c- p>,</c-> <c- k>this</c-><c- p>.</c->_onClick<c- p>.</c->bind<c- p>(</c-><c- k>this</c-><c- p>));</c->

<mark>    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->role <c- o>=</c-> <c- t>&apos;checkbox&apos;</c-><c- p>;</c->
    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaChecked <c- o>=</c-> <c- t>&apos;false&apos;</c-><c- p>;</c-></mark>
  <c- p>}</c->

  get form<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->form<c- p>;</c-> <c- p>}</c->
  get name<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->getAttribute<c- p>(</c-><c- t>&apos;name&apos;</c-><c- p>);</c-> <c- p>}</c->
  get type<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->localName<c- p>;</c-> <c- p>}</c->

  get checked<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->hasAttribute<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>);</c-> <c- p>}</c->
  set checked<c- p>(</c->flag<c- p>)</c-> <c- p>{</c-> <c- k>this</c-><c- p>.</c->toggleAttribute<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>,</c-> Boolean<c- p>(</c->flag<c- p>));</c-> <c- p>}</c->

  attributeChangedCallback<c- p>(</c->name<c- p>,</c-> oldValue<c- p>,</c-> newValue<c- p>)</c-> <c- p>{</c->
    <c- c1>// name will always be &quot;checked&quot; due to observedAttributes</c->
    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->setFormValue<c- p>(</c-><c- k>this</c-><c- p>.</c->checked <c- o>?</c-> <c- t>&apos;on&apos;</c-> <c- o>:</c-> <c- kc>null</c-><c- p>);</c->
<mark>    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaChecked <c- o>=</c-> <c- k>this</c-><c- p>.</c->checked<c- p>;</c-></mark>
  <c- p>}</c->

  _onClick<c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->checked <c- o>=</c-> <c- o>!</c-><c- k>this</c-><c- p>.</c->checked<c- p>;</c->
  <c- p>}</c->
<c- p>}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- t>&apos;my-checkbox&apos;</c-><c- p>,</c-> MyCheckbox<c- p>);</c-></code></pre>

  <p>Note that, like for built-in elements, these are only defaults, and can be overridden by the
  page author using the <code id=custom-elements-accessibility-example:attr-aria-role><a href=infrastructure.html#attr-aria-role>role</a></code> and <code id=custom-elements-accessibility-example:attr-aria-*><a href=infrastructure.html#attr-aria-*>aria-*</a></code> attributes:</p>

  <pre class=bad><code class='html'><c- c>&lt;!-- This markup is non-conforming --&gt;</c->
<c- p>&lt;</c-><c- f>input</c-> <c- e>type</c-><c- o>=</c-><c- s>&quot;checkbox&quot;</c-> <c- e>checked</c-> <c- e>role</c-><c- o>=</c-><c- s>&quot;button&quot;</c-> <c- e>aria-checked</c-><c- o>=</c-><c- s>&quot;false&quot;</c-><c- p>&gt;</c-></code></pre>

<pre class=bad><code class='html'><c- c>&lt;!-- This markup is probably not what the custom element author intended --&gt;</c->
<c- p>&lt;</c-><c- f>my-checkbox</c-> <c- e>role</c-><c- o>=</c-><c- s>&quot;button&quot;</c-> <c- e>checked</c-> <c- e>aria-checked</c-><c- o>=</c-><c- s>&quot;false&quot;</c-><c- p>&gt;</c-></code></pre>

  <p>Custom element authors are encouraged to state what aspects of their accessibility semantics
  are strong native semantics, i.e., should not be overridden by users of the custom element. In our
  example, the author of the <code>my-checkbox</code> element would state that its
  <a id=custom-elements-accessibility-example:role href=https://w3c.github.io/aria/#dfn-role data-x-internal=role>role</a> and <code id=custom-elements-accessibility-example:attr-aria-checked><a data-x-internal=attr-aria-checked href=https://w3c.github.io/aria/#aria-checked>aria-checked</a></code> values are strong
  native semantics, thus discouraging code such as the above.</p>

  <h5 id=custom-elements-customized-builtin-example><span class=secno>4.13.1.4</span> Creating a customized built-in element<a href=#custom-elements-customized-builtin-example class=self-link></a></h5>

  

  <p><a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element>Customized built-in elements</a> are a distinct
  kind of <a href=#custom-element id=custom-elements-customized-builtin-example:custom-element>custom element</a>, which are defined slightly differently and used very
  differently compared to <a href=#autonomous-custom-element id=custom-elements-customized-builtin-example:autonomous-custom-element>autonomous custom
  elements</a>. They exist to allow reuse of behaviors from the existing elements of HTML, by
  extending those elements with new custom functionality. This is important since many of the
  existing behaviors of HTML elements can unfortunately not be duplicated by using purely <a href=#autonomous-custom-element id=custom-elements-customized-builtin-example:autonomous-custom-element-2>autonomous custom elements</a>. Instead, <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-2>customized built-in elements</a> allow the installation of
  custom construction behavior, lifecycle hooks, and prototype chain onto existing elements,
  essentially "mixing in" these capabilities on top of the already-existing element.</p>

  <p><a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-3>Customized built-in elements</a> require a
  distinct syntax from <a href=#autonomous-custom-element id=custom-elements-customized-builtin-example:autonomous-custom-element-3>autonomous custom elements</a>
  because user agents and other software key off an element's local name in order to identify the
  element's semantics and behavior. That is, the concept of <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-4>customized built-in elements</a> building on top of existing behavior depends
  crucially on the extended elements retaining their original local name.</p>

  <p>In this example, we'll be creating a <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-5>customized built-in element</a> named <code>plastic-button</code>, which behaves like a normal button but gets fancy animation
  effects added whenever you click on it. We start by defining a class, just like before, although
  this time we extend <code>HTMLButtonElement</code> instead of <code>HTMLElement</code>:</p>

  <pre><code class='js'><c- a>class</c-> PlasticButton <c- k>extends</c-> HTMLButtonElement <c- p>{</c->
  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->

    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- u>&quot;click&quot;</c-><c- p>,</c-> <c- p>()</c-> <c- p>=&gt;</c-> <c- p>{</c->
      <c- c1>// Draw some fancy animation effects!</c->
    <c- p>});</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

  <p>When defining our custom element, we have to also specify the <code>extends</code> option:</p>

  <pre><code class='js'>customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;plastic-button&quot;</c-><c- p>,</c-> PlasticButton<c- p>,</c-> <c- p>{</c-> <c- k>extends</c-><c- o>:</c-> <c- u>&quot;button&quot;</c-> <c- p>});</c-></code></pre>

  <p>In general, the name of the element being extended cannot be determined simply by looking at
  what element interface it extends, as many elements share the same interface (such as
  <code id=custom-elements-customized-builtin-example:the-q-element><a href=text-level-semantics.html#the-q-element>q</a></code> and <code id=custom-elements-customized-builtin-example:the-blockquote-element><a href=grouping-content.html#the-blockquote-element>blockquote</a></code> both sharing <code>HTMLQuoteElement</code>).</p>

  <p>To construct our <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-6>customized built-in element</a> from parsed HTML source text, we use
  the <code id=custom-elements-customized-builtin-example:attr-is><a href=#attr-is>is</a></code> attribute on a <code id=custom-elements-customized-builtin-example:the-button-element><a href=form-elements.html#the-button-element>button</a></code> element:</p>

  <pre><code class='html'><c- p>&lt;</c-><c- f>button</c-> <c- e>is</c-><c- o>=</c-><c- s>&quot;plastic-button&quot;</c-><c- p>&gt;</c->Click Me!<c- p>&lt;/</c-><c- f>button</c-><c- p>&gt;</c-></code></pre>

  <p>Trying to use a <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-7>customized built-in element</a> as an <a href=#autonomous-custom-element id=custom-elements-customized-builtin-example:autonomous-custom-element-4>autonomous custom
  element</a> will <em>not</em> work; that is, <code>&lt;plastic-button>Click
  me?&lt;/plastic-button></code> will simply create an <code>HTMLElement</code> with no special
  behavior.</p>

  <p>If you need to create a customized built-in element programmatically, you can use the following
  form of <code id=custom-elements-customized-builtin-example:dom-document-createelement><a data-x-internal=dom-document-createelement href=https://dom.spec.whatwg.org/#dom-document-createelement>createElement()</a></code>:</p>

  <pre><code class='js'><c- a>const</c-> plasticButton <c- o>=</c-> document<c- p>.</c->createElement<c- p>(</c-><c- u>&quot;button&quot;</c-><c- p>,</c-> <c- p>{</c-> is<c- o>:</c-> <c- u>&quot;plastic-button&quot;</c-> <c- p>});</c->
plasticButton<c- p>.</c->textContent <c- o>=</c-> <c- u>&quot;Click me!&quot;</c-><c- p>;</c-></code></pre>

  <p>And as before, the constructor will also work:</p>

  <pre><code class='js'><c- a>const</c-> plasticButton2 <c- o>=</c-> <c- k>new</c-> PlasticButton<c- p>();</c->
console<c- p>.</c->log<c- p>(</c->plasticButton2<c- p>.</c->localName<c- p>);</c->  <c- c1>// will output &quot;button&quot;</c->
console<c- p>.</c->assert<c- p>(</c->plasticButton2 <c- k>instanceof</c-> PlasticButton<c- p>);</c->
console<c- p>.</c->assert<c- p>(</c->plasticButton2 <c- k>instanceof</c-> HTMLButtonElement<c- p>);</c-></code></pre>

  <p>Note that when creating a customized built-in element programmatically, the <code id=custom-elements-customized-builtin-example:attr-is-2><a href=#attr-is>is</a></code> attribute will not be present in the DOM, since it was not explicitly
  set. However, <a href=#attr-is-during-serialization>it will be added to the output when
  serializing</a>:</p>

  <pre><code class='js'>console<c- p>.</c->assert<c- p>(</c-><c- o>!</c->plasticButton<c- p>.</c->hasAttribute<c- p>(</c-><c- u>&quot;is&quot;</c-><c- p>));</c->
console<c- p>.</c->log<c- p>(</c->plasticButton<c- p>.</c->outerHTML<c- p>);</c-> <c- c1>// will output &apos;&lt;button is=&quot;plastic-button&quot;&gt;&lt;/button&gt;&apos;</c-></code></pre>

  <p>Regardless of how it is created, all of the ways in which <code id=custom-elements-customized-builtin-example:the-button-element-2><a href=form-elements.html#the-button-element>button</a></code> is special
  apply to such "plastic buttons" as well: their focus behavior, ability to participate in <span>form submission</span>, the <code id=custom-elements-customized-builtin-example:attr-fe-disabled><a href=form-control-infrastructure.html#attr-fe-disabled>disabled</a></code> attribute, and so on.</p>

  <p id=customized-built-in-element-restrictions><a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-8>Customized built-in elements</a> are designed to allow extension of existing HTML
  elements that have useful user-agent supplied behavior or APIs. As such, they can only extend
  existing HTML elements defined in this specification, and cannot extend legacy elements such as
  <code id=custom-elements-customized-builtin-example:bgsound><a href=obsolete.html#bgsound>bgsound</a></code>, <code id=custom-elements-customized-builtin-example:blink><a href=obsolete.html#blink>blink</a></code>, <code id=custom-elements-customized-builtin-example:isindex><a href=obsolete.html#isindex>isindex</a></code>, <code id=custom-elements-customized-builtin-example:keygen><a href=obsolete.html#keygen>keygen</a></code>,
  <code id=custom-elements-customized-builtin-example:multicol><a href=obsolete.html#multicol>multicol</a></code>, <code id=custom-elements-customized-builtin-example:nextid><a href=obsolete.html#nextid>nextid</a></code>, or <code id=custom-elements-customized-builtin-example:spacer><a href=obsolete.html#spacer>spacer</a></code> that have been defined to use
  <code>HTMLUnknownElement</code> as their <a id=custom-elements-customized-builtin-example:element-interface href=https://dom.spec.whatwg.org/#concept-element-interface data-x-internal=element-interface>element interface</a>.</p>

  <p>One reason for this requirement is future-compatibility: if a <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-9>customized built-in
  element</a> was defined that extended a currently-unknown element, for example <code>combobox</code>, this would prevent this specification from defining a <code>combobox</code> element in the future, as consumers of the derived <a href=#customized-built-in-element id=custom-elements-customized-builtin-example:customized-built-in-element-10>customized
  built-in element</a> would have come to depend on their base element having no interesting
  user-agent-supplied behavior.</p>

  <h5 id=custom-elements-autonomous-drawbacks><span class=secno>4.13.1.5</span> Drawbacks of autonomous custom elements<a href=#custom-elements-autonomous-drawbacks class=self-link></a></h5>

  

  <p>As specified below, and alluded to above, simply defining and using an element called
  <code>taco-button</code> does not mean that such elements <a href=dom.html#represents id=custom-elements-autonomous-drawbacks:represents>represent</a> buttons. That is, tools such as web browsers, search engines,
  or accessibility technology will not automatically treat the resulting element as a button just
  based on its defined name.</p>

  <p>To convey the desired button semantics to a variety of users, while still using an
  <a href=#autonomous-custom-element id=custom-elements-autonomous-drawbacks:autonomous-custom-element>autonomous custom element</a>, a number of techniques would need to be employed:</p>

  <ul><li><p>The addition of the <code id=custom-elements-autonomous-drawbacks:attr-tabindex><a href=interaction.html#attr-tabindex>tabindex</a></code> attribute would make the
   <code>taco-button</code> <span>focusable</span>. Note that if the
   <code>taco-button</code> were to become logically disabled, the <code id=custom-elements-autonomous-drawbacks:attr-tabindex-2><a href=interaction.html#attr-tabindex>tabindex</a></code> attribute would need to be removed.<li><p>The addition of an ARIA role and various ARIA states and properties helps convey semantics
   to accessibility technology. For example, setting the <a id=custom-elements-autonomous-drawbacks:role href=https://w3c.github.io/aria/#dfn-role data-x-internal=role>role</a> to "<code id=custom-elements-autonomous-drawbacks:attr-aria-role-button><a data-x-internal=attr-aria-role-button href=https://w3c.github.io/aria/#button>button</a></code>" will convey the semantics that this is a button,
   enabling users to successfully interact with the control using usual button-like interactions in
   their accessibility technology. Setting the <code id=custom-elements-autonomous-drawbacks:attr-aria-label><a data-x-internal=attr-aria-label href=https://w3c.github.io/aria/#aria-label>aria-label</a></code>
   property is necessary to give the button an <a href=https://w3c.github.io/aria/#dfn-accessible-name id=custom-elements-autonomous-drawbacks:concept-accessible-name data-x-internal=concept-accessible-name>accessible
   name</a>, instead of having accessibility technology traverse its child text nodes and
   announce them. And setting the <code id=custom-elements-autonomous-drawbacks:attr-aria-disabled><a data-x-internal=attr-aria-disabled href=https://w3c.github.io/aria/#aria-disabled>aria-disabled</a></code> state to
   "<code>true</code>" when the button is logically disabled conveys to accessibility
   technology the button's disabled state.<li><p>The addition of event handlers to handle commonly-expected button behaviors helps convey
   the semantics of the button to web browser users. In this case, the most relevant event handler
   would be one that proxies appropriate <code id=custom-elements-autonomous-drawbacks:event-keydown><a data-x-internal=event-keydown href=https://w3c.github.io/uievents/#event-type-keydown>keydown</a></code> events to
   become <code id=custom-elements-autonomous-drawbacks:event-click><a data-x-internal=event-click href=https://w3c.github.io/uievents/#event-type-click>click</a></code> events, so that you can activate the button both
   with keyboard and by clicking.<li><p>In addition to any default visual styling provided for <code>taco-button</code>
   elements, the visual styling will also need to be updated to reflect changes in logical state,
   such as becoming disabled; that is, whatever style sheet has rules for <code>taco-button</code> will also need to have rules for <code>taco-button[disabled]</code>.</ul>

  <p>With these points in mind, a full-featured <code>taco-button</code> that took on the
  responsibility of conveying button semantics (including the ability to be disabled) might look
  something like this:</p>

  <pre id=custom-elements-autonomous-drawbacks-example><code class='js'><c- a>class</c-> TacoButton <c- k>extends</c-> HTMLElement <c- p>{</c->
  <c- k>static</c-> observedAttributes <c- o>=</c-> <c- p>[</c-><c- u>&quot;disabled&quot;</c-><c- p>];</c->

  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachInternals<c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->role <c- o>=</c-> <c- u>&quot;button&quot;</c-><c- p>;</c->

    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- u>&quot;keydown&quot;</c-><c- p>,</c-> e <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>if</c-> <c- p>(</c->e<c- p>.</c->code <c- o>===</c-> <c- u>&quot;Enter&quot;</c-> <c- o>||</c-> e<c- p>.</c->code <c- o>===</c-> <c- u>&quot;Space&quot;</c-><c- p>)</c-> <c- p>{</c->
        <c- k>this</c-><c- p>.</c->dispatchEvent<c- p>(</c-><c- k>new</c-> PointerEvent<c- p>(</c-><c- u>&quot;click&quot;</c-><c- p>,</c-> <c- p>{</c->
          bubbles<c- o>:</c-> <c- kc>true</c-><c- p>,</c->
          cancelable<c- o>:</c-> <c- kc>true</c->
        <c- p>}));</c->
      <c- p>}</c->
    <c- p>});</c->

    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- u>&quot;click&quot;</c-><c- p>,</c-> e <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>if</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->disabled<c- p>)</c-> <c- p>{</c->
        e<c- p>.</c->preventDefault<c- p>();</c->
        e<c- p>.</c->stopImmediatePropagation<c- p>();</c->
      <c- p>}</c->
    <c- p>});</c->

    <c- k>this</c-><c- p>.</c->_observer <c- o>=</c-> <c- k>new</c-> MutationObserver<c- p>(()</c-> <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaLabel <c- o>=</c-> <c- k>this</c-><c- p>.</c->textContent<c- p>;</c->
    <c- p>});</c->
  <c- p>}</c->

  connectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->setAttribute<c- p>(</c-><c- u>&quot;tabindex&quot;</c-><c- p>,</c-> <c- u>&quot;0&quot;</c-><c- p>);</c->

    <c- k>this</c-><c- p>.</c->_observer<c- p>.</c->observe<c- p>(</c-><c- k>this</c-><c- p>,</c-> <c- p>{</c->
      childList<c- o>:</c-> <c- kc>true</c-><c- p>,</c->
      characterData<c- o>:</c-> <c- kc>true</c-><c- p>,</c->
      subtree<c- o>:</c-> <c- kc>true</c->
    <c- p>});</c->
  <c- p>}</c->

  disconnectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->_observer<c- p>.</c->disconnect<c- p>();</c->
  <c- p>}</c->

  get disabled<c- p>()</c-> <c- p>{</c->
    <c- k>return</c-> <c- k>this</c-><c- p>.</c->hasAttribute<c- p>(</c-><c- u>&quot;disabled&quot;</c-><c- p>);</c->
  <c- p>}</c->
  set disabled<c- p>(</c->flag<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->toggleAttribute<c- p>(</c-><c- u>&quot;disabled&quot;</c-><c- p>,</c-> Boolean<c- p>(</c->flag<c- p>));</c->
  <c- p>}</c->

  attributeChangedCallback<c- p>(</c->name<c- p>,</c-> oldValue<c- p>,</c-> newValue<c- p>)</c-> <c- p>{</c->
    <c- c1>// name will always be &quot;disabled&quot; due to observedAttributes</c->
    <c- k>if</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->disabled<c- p>)</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->removeAttribute<c- p>(</c-><c- u>&quot;tabindex&quot;</c-><c- p>);</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaDisabled <c- o>=</c-> <c- u>&quot;true&quot;</c-><c- p>;</c->
    <c- p>}</c-> <c- k>else</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->setAttribute<c- p>(</c-><c- u>&quot;tabindex&quot;</c-><c- p>,</c-> <c- u>&quot;0&quot;</c-><c- p>);</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaDisabled <c- o>=</c-> <c- u>&quot;false&quot;</c-><c- p>;</c->
    <c- p>}</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

  <p>Even with this rather-complicated element definition, the element is not a pleasure to use for
  consumers: it will be continually "sprouting" <code id=custom-elements-autonomous-drawbacks:attr-tabindex-3><a href=interaction.html#attr-tabindex>tabindex</a></code>
  attributes of its own volition, and its choice of <code>tabindex="0"</code> focusability
  behavior may not match the <code id=custom-elements-autonomous-drawbacks:the-button-element><a href=form-elements.html#the-button-element>button</a></code> behavior on the current platform. This is because
  as of now there is no way to specify default focus behavior for custom elements, forcing the use
  of the <code id=custom-elements-autonomous-drawbacks:attr-tabindex-4><a href=interaction.html#attr-tabindex>tabindex</a></code> attribute to do so (even though it is usually
  reserved for allowing the consumer to override default behavior).</p>

  <p>In contrast, a simple <a href=#customized-built-in-element id=custom-elements-autonomous-drawbacks:customized-built-in-element>customized built-in element</a>, as shown in the previous
  section, would automatically inherit the semantics and behavior of the <code id=custom-elements-autonomous-drawbacks:the-button-element-2><a href=form-elements.html#the-button-element>button</a></code>
  element, with no need to implement these behaviors manually. In general, for any elements with
  nontrivial behavior and semantics that build on top of existing elements of HTML, <a href=#customized-built-in-element id=custom-elements-autonomous-drawbacks:customized-built-in-element-2>customized built-in elements</a> will be easier to
  develop, maintain, and consume.</p>

  <h5 id=custom-elements-upgrades-examples><span class=secno>4.13.1.6</span> Upgrading elements after their creation<a href=#custom-elements-upgrades-examples class=self-link></a></h5>

  

  <p>Because <a href=#element-definition id=custom-elements-upgrades-examples:element-definition>element definition</a> can occur at any time, a non-custom element could be
  <a href=https://dom.spec.whatwg.org/#concept-create-element id=custom-elements-upgrades-examples:create-an-element data-x-internal=create-an-element>created</a>, and then later become a <a href=#custom-element id=custom-elements-upgrades-examples:custom-element>custom
  element</a> after an appropriate <span>definition</span> is
  registered. We call this process "upgrading" the element, from a normal element into a custom
  element.</p>

  <p><span>Upgrades</span> enable scenarios where it may be
  preferable for <span>custom element definitions</span> to be
  registered after relevant elements have been initially created, such as by the parser. They allow
  progressive enhancement of the content in the custom element. For example, in the following HTML
  document the element definition for <code>img-viewer</code> is loaded
  asynchronously:</p>

  <pre><code class='html'><c- cp>&lt;!DOCTYPE html&gt;</c->
<c- p>&lt;</c-><c- f>html</c-> <c- e>lang</c-><c- o>=</c-><c- s>&quot;en&quot;</c-><c- p>&gt;</c->
<c- p>&lt;</c-><c- f>title</c-><c- p>&gt;</c->Image viewer example<c- p>&lt;/</c-><c- f>title</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>img-viewer</c-> <c- e>filter</c-><c- o>=</c-><c- s>&quot;Kelvin&quot;</c-><c- p>&gt;</c->
  <c- p>&lt;</c-><c- f>img</c-> <c- e>src</c-><c- o>=</c-><c- s>&quot;images/tree.jpg&quot;</c-> <c- e>alt</c-><c- o>=</c-><c- s>&quot;A beautiful tree towering over an empty savannah&quot;</c-><c- p>&gt;</c->
<c- p>&lt;/</c-><c- f>img-viewer</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>script</c-> <c- e>src</c-><c- o>=</c-><c- s>&quot;js/elements/img-viewer.js&quot;</c-> <c- e>async</c-><c- p>&gt;&lt;/</c-><c- f>script</c-><c- p>&gt;</c-></code></pre>

  <p>The definition for the <code>img-viewer</code> element here is loaded using a
  <code id=custom-elements-upgrades-examples:the-script-element><a href=scripting.html#the-script-element>script</a></code> element marked with the <code id=custom-elements-upgrades-examples:attr-script-async><a href=scripting.html#attr-script-async>async</a></code>
  attribute, placed after the <code>&lt;img-viewer></code> tag in the markup. While the
  script is loading, the <code>img-viewer</code> element will be treated as an undefined
  element, similar to a <code id=custom-elements-upgrades-examples:the-span-element><a href=text-level-semantics.html#the-span-element>span</a></code>. Once the script loads, it will define the <code>img-viewer</code> element, and the existing <code>img-viewer</code> element on
  the page will be upgraded, applying the custom element's definition (which presumably includes
  applying an image filter identified by the string "Kelvin", enhancing the image's visual
  appearance).</p>

  <hr>

  <p>Note that <span>upgrades</span> only apply to elements in the
  document tree. (Formally, elements that are <a id=custom-elements-upgrades-examples:connected href=https://dom.spec.whatwg.org/#connected data-x-internal=connected>connected</a>.) An element that is not
  inserted into a document will stay un-upgraded. An example illustrates this point:</p>

  <pre><code class='html'><c- cp>&lt;!DOCTYPE html&gt;</c->
<c- p>&lt;</c-><c- f>html</c-> <c- e>lang</c-><c- o>=</c-><c- s>&quot;en&quot;</c-><c- p>&gt;</c->
<c- p>&lt;</c-><c- f>title</c-><c- p>&gt;</c->Upgrade edge-cases example<c- p>&lt;/</c-><c- f>title</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>example-element</c-><c- p>&gt;&lt;/</c-><c- f>example-element</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>script</c-><c- p>&gt;</c->
  <c- u>&quot;use strict&quot;</c-><c- p>;</c->

  <c- a>const</c-> inDocument <c- o>=</c-> document<c- p>.</c->querySelector<c- p>(</c-><c- u>&quot;example-element&quot;</c-><c- p>);</c->
  <c- a>const</c-> outOfDocument <c- o>=</c-> document<c- p>.</c->createElement<c- p>(</c-><c- u>&quot;example-element&quot;</c-><c- p>);</c->

  <c- c1>// Before the element definition, both are HTMLElement:</c->
  console<c- p>.</c->assert<c- p>(</c->inDocument <c- k>instanceof</c-> HTMLElement<c- p>);</c->
  console<c- p>.</c->assert<c- p>(</c->outOfDocument <c- k>instanceof</c-> HTMLElement<c- p>);</c->

  <c- a>class</c-> ExampleElement <c- k>extends</c-> HTMLElement <c- p>{}</c->
  customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;example-element&quot;</c-><c- p>,</c-> ExampleElement<c- p>);</c->

  <c- c1>// After element definition, the in-document element was upgraded:</c->
  console<c- p>.</c->assert<c- p>(</c->inDocument <c- k>instanceof</c-> ExampleElement<c- p>);</c->
  console<c- p>.</c->assert<c- p>(</c-><c- o>!</c-><c- p>(</c->outOfDocument <c- k>instanceof</c-> ExampleElement<c- p>));</c->

  document<c- p>.</c->body<c- p>.</c->appendChild<c- p>(</c->outOfDocument<c- p>);</c->

  <c- c1>// Now that we&apos;ve moved the element into the document, it too was upgraded:</c->
  console<c- p>.</c->assert<c- p>(</c->outOfDocument <c- k>instanceof</c-> ExampleElement<c- p>);</c->
<c- p>&lt;/</c-><c- f>script</c-><c- p>&gt;</c-></code></pre>

  <h5 id=scoped-custom-element-registries><span class=secno>4.13.1.7</span> Scoped custom element registries<a href=#scoped-custom-element-registries class=self-link></a></h5>

  <p>To allow multiple libraries to co-exist without explicit coordination,
  <code>CustomElementRegistry</code> can be used in a scoped fashion as well.</p>

  <pre><code class='js'><c- a>const</c-> scoped <c- o>=</c-> <c- k>new</c-> CustomElementRegistry<c- p>();</c->
scoped<c- p>.</c->define<c- p>(</c-><c- u>&quot;example-element&quot;</c-><c- p>,</c-> ExampleElement<c- p>);</c->

<c- a>const</c-> element <c- o>=</c-> document<c- p>.</c->createElement<c- p>(</c-><c- u>&quot;example-element&quot;</c-><c- p>,</c-> <c- p>{</c-> customElementRegistry<c- o>:</c-> scoped <c- p>});</c-></code></pre>

  <p>A node with an associated scoped <code>CustomElementRegistry</code> will use that registry for
  all its operations, such as when invoking <code id=scoped-custom-element-registries:dom-element-sethtmlunsafe><a href=dynamic-markup-insertion.html#dom-element-sethtmlunsafe>setHTMLUnsafe()</a></code>.</p>

  <h5 id=exposing-custom-element-states><span class=secno>4.13.1.8</span> Exposing custom element states<a href=#exposing-custom-element-states class=self-link></a></h5>

  <p>Built-in elements provided by user agents have certain states that can change over time
  depending on user interaction and other factors, and are exposed to web authors through <a href=https://drafts.csswg.org/selectors/#pseudo-class id=exposing-custom-element-states:pseudo-class data-x-internal=pseudo-class>pseudo-classes</a>. For example, some form controls have the "invalid"
  state, which is exposed through the <code>:invalid</code>
  <a id=exposing-custom-element-states:pseudo-class-2 href=https://drafts.csswg.org/selectors/#pseudo-class data-x-internal=pseudo-class>pseudo-class</a>.</p>

  <p>Like built-in elements, <a href=#custom-element id=exposing-custom-element-states:custom-element>custom elements</a> can have various
  states to be in too, and <a href=#custom-element id=exposing-custom-element-states:custom-element-2>custom element</a> authors want to expose these states in a
  similar fashion as the built-in elements.</p>

  <p>This is done via the <code>:state()</code> pseudo-class. A custom
  element author can use the <code>states</code> property of
  <code>ElementInternals</code> to add and remove such custom states, which are then exposed as
  arguments to the <code>:state()</code> pseudo-class.

  <div class=example>
   <p>The following shows how <code>:state()</code> can be used to style a
   custom checkbox element. Assume that <code>LabeledCheckbox</code> doesn't expose its
   "checked" state via a content attribute.</p>

   <pre><code class='html'><c- p>&lt;</c-><c- f>script</c-><c- p>&gt;</c->
<c- a>class</c-> LabeledCheckbox <c- k>extends</c-> HTMLElement <c- p>{</c->
  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachInternals<c- p>();</c->
    <c- k>this</c-><c- p>.</c->addEventListener<c- p>(</c-><c- t>&apos;click&apos;</c-><c- p>,</c-> <c- k>this</c-><c- p>.</c->_onClick<c- p>.</c->bind<c- p>(</c-><c- k>this</c-><c- p>));</c->

    <c- a>const</c-> shadowRoot <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachShadow<c- p>({</c->mode<c- o>:</c-> <c- t>&apos;closed&apos;</c-><c- p>});</c->
    shadowRoot<c- p>.</c->innerHTML <c- o>=</c->
      <c- sb>`&lt;style&gt;</c->
<c- sb>       :host::before {</c->
<c- sb>         content: &apos;[ ]&apos;;</c->
<c- sb>         white-space: pre;</c->
<c- sb>         font-family: monospace;</c->
<c- sb>       }</c->
<c- sb>       :host(:state(checked))::before { content: &apos;[x]&apos; }</c->
<c- sb>       &lt;/style&gt;</c->
<c- sb>       &lt;slot&gt;Label&lt;/slot&gt;`</c-><c- p>;</c->
  <c- p>}</c->

  get checked<c- p>()</c-> <c- p>{</c-> <c- k>return</c-> <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c->has<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>);</c-> <c- p>}</c->

  set checked<c- p>(</c->flag<c- p>)</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c->flag<c- p>)</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c->add<c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>);</c->
    <c- k>else</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c-><c- k>delete</c-><c- p>(</c-><c- t>&apos;checked&apos;</c-><c- p>);</c->
  <c- p>}</c->

  _onClick<c- p>(</c->event<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->checked <c- o>=</c-> <c- o>!</c-><c- k>this</c-><c- p>.</c->checked<c- p>;</c->
  <c- p>}</c->
<c- p>}</c->

customElements<c- p>.</c->define<c- p>(</c-><c- t>&apos;labeled-checkbox&apos;</c-><c- p>,</c-> LabeledCheckbox<c- p>);</c->
<c- p>&lt;/</c-><c- f>script</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>style</c-><c- p>&gt;</c->
<c- f>labeled-checkbox</c-> <c- p>{</c-> <c- k>border</c-><c- p>:</c-> <c- kc>dashed</c-> <c- kc>red</c-><c- p>;</c-> <c- p>}</c->
<c- f>labeled-checkbox</c-><c- p>:</c-><c- nd>state</c-><c- o>(</c-><c- f>checked</c-><c- o>)</c-> <c- p>{</c-> <c- k>border</c-><c- p>:</c-> <c- kc>solid</c-><c- p>;</c-> <c- p>}</c->
<c- p>&lt;/</c-><c- f>style</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>labeled-checkbox</c-><c- p>&gt;</c->You need to check this<c- p>&lt;/</c-><c- f>labeled-checkbox</c-><c- p>&gt;</c-></code></pre>
  </div>

  <div class=example>
   <p>Custom pseudo-classes can even target shadow parts. An extension of the above example shows
   this:</p>

   <pre><code class='html'><c- p>&lt;</c-><c- f>script</c-><c- p>&gt;</c->
<c- a>class</c-> QuestionBox <c- k>extends</c-> HTMLElement <c- p>{</c->
  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- a>const</c-> shadowRoot <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachShadow<c- p>({</c->mode<c- o>:</c-> <c- t>&apos;closed&apos;</c-><c- p>});</c->
    shadowRoot<c- p>.</c->innerHTML <c- o>=</c->
      <c- sb>`&lt;div&gt;&lt;slot&gt;Question&lt;/slot&gt;&lt;/div&gt;</c->
<c- sb>       &lt;labeled-checkbox part=&apos;checkbox&apos;&gt;Yes&lt;/labeled-checkbox&gt;`</c-><c- p>;</c->
  <c- p>}</c->
<c- p>}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- t>&apos;question-box&apos;</c-><c- p>,</c-> QuestionBox<c- p>);</c->
<c- p>&lt;/</c-><c- f>script</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>style</c-><c- p>&gt;</c->
<c- f>question-box</c-><c- p>::</c-><c- nd>part</c-><c- o>(</c-><c- f>checkbox</c-><c- o>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> <c- kc>red</c-><c- p>;</c-> <c- p>}</c->
<c- f>question-box</c-><c- p>::</c-><c- nd>part</c-><c- o>(</c-><c- f>checkbox</c-><c- o>)</c-><c- p>:</c-><c- nd>state</c-><c- o>(</c-><c- f>checked</c-><c- o>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> <c- kc>green</c-><c- p>;</c-> <c- p>}</c->
<c- p>&lt;/</c-><c- f>style</c-><c- p>&gt;</c->

<c- p>&lt;</c-><c- f>question-box</c-><c- p>&gt;</c->Continue?<c- p>&lt;/</c-><c- f>question-box</c-><c- p>&gt;</c-></code></pre>
  </div>

  <h4 id=custom-element-conformance><span class=secno>4.13.2</span> Requirements for custom element constructors and
  reactions<a href=#custom-element-conformance class=self-link></a></h4>

  <p>When authoring <a href=#custom-element-constructor id=custom-element-conformance:custom-element-constructor>custom element constructors</a>,
  authors are bound by the following conformance requirements:</p>

  <ul><li><p>A parameter-less call to <code>super()</code> must be the first statement in the
   constructor body, to establish the correct prototype chain and <b>this</b> value before any
   further code is run.<li><p>A <code>return</code> statement must not appear anywhere inside the constructor
   body, unless it is a simple early-return (<code>return</code> or <code>return
   this</code>).<li><p>The constructor must not use the <code id=custom-element-conformance:dom-document-write><a href=dynamic-markup-insertion.html#dom-document-write>document.write()</a></code>
   or <code id=custom-element-conformance:dom-document-open><a href=dynamic-markup-insertion.html#dom-document-open>document.open()</a></code> methods.<li><p>The element's attributes and children must not be inspected, as in the non-<span>upgrade</span> case none will be present, and relying on
   upgrades makes the element less usable.<li><p>The element must not gain any attributes or children, as this violates the expectations of
   consumers who use the <code id=custom-element-conformance:dom-document-createelement><a data-x-internal=dom-document-createelement href=https://dom.spec.whatwg.org/#dom-document-createelement>createElement</a></code> or <code id=custom-element-conformance:dom-document-createelementns><a data-x-internal=dom-document-createelementns href=https://dom.spec.whatwg.org/#dom-document-createelementns>createElementNS</a></code> methods.<li><p>In general, work should be deferred to <code>connectedCallback</code> as much as
   possible—especially work involving fetching resources or rendering. However, note that <code>connectedCallback</code> can be called more than once, so any initialization work that
   is truly one-time will need a guard to prevent it from running twice.<li><p>In general, the constructor should be used to set up initial state and default values, and
   to set up event listeners and possibly a <a id=custom-element-conformance:shadow-root href=https://dom.spec.whatwg.org/#concept-shadow-root data-x-internal=shadow-root>shadow root</a>.</ul>

  <p>Several of these requirements are checked during <a href=https://dom.spec.whatwg.org/#concept-create-element id=custom-element-conformance:create-an-element data-x-internal=create-an-element>element
  creation</a>, either directly or indirectly, and failing to follow them will result in a custom
  element that cannot be instantiated by the parser or DOM APIs. This is true even if the work is
  done inside a constructor-initiated <span>microtask</span>, as a <span>microtask checkpoint</span> can occur immediately after construction.</p>

  <p>When authoring <a href=#concept-custom-element-reaction id=custom-element-conformance:concept-custom-element-reaction>custom element reactions</a>,
  authors should avoid manipulating the node tree as this can lead to unexpected results.</p>

  <div class=example>
   <p>An element's <code>connectedCallback</code> can be queued before the element is
   disconnected, but as the callback queue is still processed, it results in a <code>connectedCallback</code> for an element that is no longer connected:</p>

   <pre><code class='js'><c- a>class</c-> CParent <c- k>extends</c-> HTMLElement <c- p>{</c->
  connectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->firstChild<c- p>.</c->remove<c- p>();</c->
  <c- p>}</c->
<c- p>}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;c-parent&quot;</c-><c- p>,</c-> CParent<c- p>);</c->

<c- a>class</c-> CChild <c- k>extends</c-> HTMLElement <c- p>{</c->
  connectedCallback<c- p>()</c-> <c- p>{</c->
    console<c- p>.</c->log<c- p>(</c-><c- u>&quot;CChild connectedCallback: isConnected =&quot;</c-><c- p>,</c-> <c- k>this</c-><c- p>.</c->isConnected<c- p>);</c->
  <c- p>}</c->
<c- p>}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;c-child&quot;</c-><c- p>,</c-> CChild<c- p>);</c->

<c- a>const</c-> parent <c- o>=</c-> <c- k>new</c-> CParent<c- p>(),</c->
      child <c- o>=</c-> <c- k>new</c-> CChild<c- p>();</c->
parent<c- p>.</c->append<c- p>(</c->child<c- p>);</c->
document<c- p>.</c->body<c- p>.</c->append<c- p>(</c->parent<c- p>);</c->

<c- c1>// Logs:</c->
<c- c1>// CChild connectedCallback: isConnected = false</c-></code></pre>
  </div>

  <h5 id=preserving-custom-element-state-when-moved><span class=secno>4.13.2.1</span> Preserving custom element state when moved<a href=#preserving-custom-element-state-when-moved class=self-link></a></h5>

  

  <p>When manipulating the DOM tree, an element can be <a href=https://dom.spec.whatwg.org/#concept-node-move-ext id=preserving-custom-element-state-when-moved:concept-node-move-ext data-x-internal=concept-node-move-ext>moved</a> in the tree while connected. This applies to custom
  elements as well. By default, the "<code>disconnectedCallback</code>" and "<code>connectedCallback</code>" would be called on the element, one after the other. This is
  done to maintain compatibility with existing custom elements that predate the <code id=preserving-custom-element-state-when-moved:dom-parentnode-movebefore><a data-x-internal=dom-parentnode-movebefore href=https://dom.spec.whatwg.org/#dom-parentnode-movebefore>moveBefore()</a></code> method. This means that by default, custom
  elements reset their state as if they were removed and re-inserted. In the example <a href=#custom-elements-autonomous-drawbacks-example>above</a>, the impact would be that the
  observer would be disconnected and re-connected, and the tab index would be reset.</p>

  <p>To opt in to a state-preserving behavior while <a href=https://dom.spec.whatwg.org/#concept-node-move-ext id=preserving-custom-element-state-when-moved:concept-node-move-ext-2 data-x-internal=concept-node-move-ext>moving</a>, the author can implement a "<code>connectedMoveCallback</code>". The existence of this callback, even if empty, would
  supersede the default behavior of calling "<code>disconnectedCallback</code>" and "<code>connectedCallback</code>". "<code>connectedMoveCallback</code>" can also be an
  appropriate place to execute logic that depends on the element's ancestors. For example:</p>

  <pre><code class='js'><c- a>class</c-> TacoButton <c- k>extends</c-> HTMLElement <c- p>{</c->
  <c- k>static</c-> observedAttributes <c- o>=</c-> <c- p>[</c-><c- u>&quot;disabled&quot;</c-><c- p>];</c->

  constructor<c- p>()</c-> <c- p>{</c->
    <c- k>super</c-><c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals <c- o>=</c-> <c- k>this</c-><c- p>.</c->attachInternals<c- p>();</c->
    <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->role <c- o>=</c-> <c- u>&quot;button&quot;</c-><c- p>;</c->

    <c- k>this</c-><c- p>.</c->_observer <c- o>=</c-> <c- k>new</c-> MutationObserver<c- p>(()</c-> <c- p>=&gt;</c-> <c- p>{</c->
      <c- k>this</c-><c- p>.</c->_internals<c- p>.</c->ariaLabel <c- o>=</c-> <c- k>this</c-><c- p>.</c->textContent<c- p>;</c->
    <c- p>});</c->
  <c- p>}</c->

  _notifyMain<c- p>()</c-> <c- p>{</c->
    <c- k>if</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->parentElement<c- p>.</c->tagName <c- o>===</c-> <c- u>&quot;MAIN&quot;</c-><c- p>)</c-> <c- p>{</c->
      <c- c1>// Execute logic that depends on ancestors.</c->
    <c- p>}</c->
  <c- p>}</c->

  connectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->setAttribute<c- p>(</c-><c- u>&quot;tabindex&quot;</c-><c- p>,</c-> <c- u>&quot;0&quot;</c-><c- p>);</c->

    <c- k>this</c-><c- p>.</c->_observer<c- p>.</c->observe<c- p>(</c-><c- k>this</c-><c- p>,</c-> <c- p>{</c->
      childList<c- o>:</c-> <c- kc>true</c-><c- p>,</c->
      characterData<c- o>:</c-> <c- kc>true</c-><c- p>,</c->
      subtree<c- o>:</c-> <c- kc>true</c->
    <c- p>});</c->

    <c- k>this</c-><c- p>.</c->_notifyMain<c- p>();</c->
  <c- p>}</c->

  disconnectedCallback<c- p>()</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->_observer<c- p>.</c->disconnect<c- p>();</c->
  <c- p>}</c->

  <c- c1>// Implementing this function would avoid resetting the tab index or re-registering the</c->
  <c- c1>// mutation observer when this element is moved inside the DOM without being disconnected.</c->
  connectedMoveCallback<c- p>()</c-> <c- p>{</c->
    <c- c1>// The parent can change during a state-preserving move.</c->
    <c- k>this</c-><c- p>.</c->_notifyMain<c- p>();</c->
  <c- p>}</c->
<c- p>}</c-></code></pre>

  <h4 id=custom-elements-core-concepts><span class=secno>4.13.3</span> Core concepts<a href=#custom-elements-core-concepts class=self-link></a></h4>

  <p>A <dfn id=custom-element data-export="">custom element</dfn> is an element that is <a href=https://dom.spec.whatwg.org/#concept-element-custom id=custom-elements-core-concepts:concept-element-custom data-x-internal=concept-element-custom>custom</a>. Informally, this means that its constructor and
  prototype are defined by the author, instead of by the user agent. This author-supplied
  constructor function is called the <dfn id=custom-element-constructor data-export="">custom element constructor</dfn>.</p>

  <p>Two distinct types of <a href=#custom-element id=custom-elements-core-concepts:custom-element>custom elements</a> can be defined:</p>

  <div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is title="The is global attribute allows you to specify that a standard HTML element should behave like a defined custom built-in element (see Using custom elements for more details).">Global_attributes/is</a><div class=support><span class="firefox yes"><span>Firefox</span><span>63+</span></span><span class="safari no"><span>Safari</span><span>No</span></span><span class="chrome yes"><span>Chrome</span><span>67+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div><ul><li><p>An <dfn id=autonomous-custom-element data-export="">autonomous custom element</dfn>, which is defined with no <code>extends</code> option. These types of custom
   elements have a local name equal to their <span>defined name</span>.<li><p>A <dfn id=customized-built-in-element data-export="">customized built-in element</dfn>, which is defined with an <code>extends</code> option. These types of custom
   elements have a local name equal to the value passed in their <code>extends</code> option, and their <span>defined name</span> is used as the value of the
   <dfn data-dfn-for=html-global id=attr-is data-dfn-type=element-attr><code>is</code></dfn> attribute, which
   therefore must be a <a href=#valid-custom-element-name id=custom-elements-core-concepts:valid-custom-element-name>valid custom element name</a>.</ul>

  <p>After a <a href=#custom-element id=custom-elements-core-concepts:custom-element-2>custom element</a> is <a href=https://dom.spec.whatwg.org/#concept-create-element id=custom-elements-core-concepts:create-an-element data-x-internal=create-an-element>created</a>,
  changing the value of the <code id=custom-elements-core-concepts:attr-is><a href=#attr-is>is</a></code> attribute does not
  change the element's behavior.</p>

  <p><a href=#autonomous-custom-element id=custom-elements-core-concepts:autonomous-custom-element>Autonomous custom elements</a> have the following
  element definition:</p>

  <dl class=element><dt><a href=dom.html#concept-element-categories id=custom-elements-core-concepts:concept-element-categories>Categories</a>:<dd><a id=custom-elements-core-concepts:flow-content-2 href=dom.html#flow-content-2>Flow content</a>.<dd><a id=custom-elements-core-concepts:phrasing-content-2 href=dom.html#phrasing-content-2>Phrasing content</a>.<dd><a id=custom-elements-core-concepts:palpable-content-2 href=dom.html#palpable-content-2>Palpable content</a>.<dd>For <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element>form-associated custom elements</a>: <a href=forms.html#category-listed id=custom-elements-core-concepts:category-listed>Listed</a>, <a href=forms.html#category-label id=custom-elements-core-concepts:category-label>labelable</a>, <a href=forms.html#category-submit id=custom-elements-core-concepts:category-submit>submittable</a>, and <a href=forms.html#category-reset id=custom-elements-core-concepts:category-reset>resettable</a> <a id=custom-elements-core-concepts:form-associated-element href=forms.html#form-associated-element>form-associated element</a>.<dt><a href=dom.html#concept-element-contexts id=custom-elements-core-concepts:concept-element-contexts>Contexts in which this element can be used</a>:<dd>Where <a id=custom-elements-core-concepts:phrasing-content-2-2 href=dom.html#phrasing-content-2>phrasing content</a> is expected.<dt><a href=dom.html#concept-element-content-model id=custom-elements-core-concepts:concept-element-content-model>Content model</a>:<dd><a id=custom-elements-core-concepts:transparent href=dom.html#transparent>Transparent</a>.<dt><a href=dom.html#concept-element-attributes id=custom-elements-core-concepts:concept-element-attributes>Content attributes</a>:<dd><a id=custom-elements-core-concepts:global-attributes href=dom.html#global-attributes>Global attributes</a>, except the <code id=custom-elements-core-concepts:attr-is-2><a href=#attr-is>is</a></code> attribute<dd><code id=custom-elements-core-concepts:attr-fae-form><a href=form-control-infrastructure.html#attr-fae-form>form</a></code>, for <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-2>form-associated custom elements</a> —  Associates the element with a <code id=custom-elements-core-concepts:the-form-element><a href=forms.html#the-form-element>form</a></code> element
     <dd><code id=custom-elements-core-concepts:attr-fe-disabled><a href=form-control-infrastructure.html#attr-fe-disabled>disabled</a></code>, for <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-3>form-associated custom elements</a> —  Whether the form control is disabled
     <dd><code id=custom-elements-core-concepts:attr-face-readonly><a href=#attr-face-readonly>readonly</a></code>, for <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-4>form-associated custom elements</a> —  Affects <code>willValidate</code>, plus any behavior added by the custom element author
     <dd><code id=custom-elements-core-concepts:attr-fe-name><a href=form-control-infrastructure.html#attr-fe-name>name</a></code>, for <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-5>form-associated custom elements</a> —  Name of the element to use for <a id=custom-elements-core-concepts:form-submission-2 href=form-control-infrastructure.html#form-submission-2>form submission</a> and in the <code id=custom-elements-core-concepts:dom-form-elements><a href=forms.html#dom-form-elements>form.elements</a></code> API 
     <dd>Any other attribute that has no namespace (see prose).<dt><a href=dom.html#concept-element-accessibility-considerations id=custom-elements-core-concepts:concept-element-accessibility-considerations>Accessibility considerations</a>:<dd>For <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-6>form-associated custom elements</a>: <a href=https://w3c.github.io/html-aria/#el-form-associated-custom-element>for authors</a>; <a href=https://w3c.github.io/html-aam/#el-form-associated-custom-element>for implementers</a>.<dd>Otherwise: <a href=https://w3c.github.io/html-aria/#el-autonomous-custom-element>for authors</a>; <a href=https://w3c.github.io/html-aam/#el-autonomous-custom-element>for implementers</a>.<dt><a href=dom.html#concept-element-dom id=custom-elements-core-concepts:concept-element-dom>DOM interface</a>:<dd>Supplied by the element's author (inherits from <code>HTMLElement</code>)</dl>


  <p>An <a href=#autonomous-custom-element id=custom-elements-core-concepts:autonomous-custom-element-2>autonomous custom element</a> does not have any special meaning: it
  <a id=custom-elements-core-concepts:represents href=dom.html#represents>represents</a> its children. A <a href=#customized-built-in-element id=custom-elements-core-concepts:customized-built-in-element>customized built-in element</a> inherits the
  semantics of the element that it extends.</p>

  <p>Any namespace-less attribute that is relevant to the element's functioning, as determined by
  the element's author, may be specified on an <a href=#autonomous-custom-element id=custom-elements-core-concepts:autonomous-custom-element-3>autonomous custom element</a>, so long as
  the attribute name is a <a id=custom-elements-core-concepts:valid-attribute-local-name href=https://dom.spec.whatwg.org/#valid-attribute-local-name data-x-internal=valid-attribute-local-name>valid attribute local name</a> and contains no <a href=https://infra.spec.whatwg.org/#ascii-upper-alpha id=custom-elements-core-concepts:uppercase-ascii-letters data-x-internal=uppercase-ascii-letters>ASCII upper alphas</a>. The exception is the <code id=custom-elements-core-concepts:attr-is-3><a href=#attr-is>is</a></code> attribute, which must not be specified on an <a href=#autonomous-custom-element id=custom-elements-core-concepts:autonomous-custom-element-4>autonomous custom
  element</a> (and which will have no effect if it is).</p>

  <p><a href=#customized-built-in-element id=custom-elements-core-concepts:customized-built-in-element-2>Customized built-in elements</a> follow the
  normal requirements for attributes, based on the elements they extend. To add custom
  attribute-based behavior, use <code id=custom-elements-core-concepts:attr-data-*><a href=dom.html#attr-data-*>data-*</a></code> attributes.</p>

  <hr>

  <p>An <a href=#autonomous-custom-element id=custom-elements-core-concepts:autonomous-custom-element-5>autonomous custom element</a> is called a <dfn id=form-associated-custom-element data-export="">form-associated custom
  element</dfn> if the element is associated with a <span>custom element definition</span> whose
  <span>form-associated</span> field is
  set to true.</p>

  <p>The <code id=custom-elements-core-concepts:attr-fe-name-2><a href=form-control-infrastructure.html#attr-fe-name>name</a></code> attribute represents the <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-7>form-associated
  custom element</a>'s name. The <code id=custom-elements-core-concepts:attr-fe-disabled-2><a href=form-control-infrastructure.html#attr-fe-disabled>disabled</a></code> attribute is
  used to make the <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-8>form-associated custom element</a> non-interactive and to prevent its
  <a href=#face-submission-value id=custom-elements-core-concepts:face-submission-value>submission value</a> from being submitted. The <code id=custom-elements-core-concepts:attr-fae-form-2><a href=form-control-infrastructure.html#attr-fae-form>form</a></code> attribute is used to explicitly associate the
  <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-9>form-associated custom element</a> with its <a id=custom-elements-core-concepts:form-owner href=form-control-infrastructure.html#form-owner>form owner</a>.</p>

  <p>The <dfn data-dfn-for="form-associated custom elements" id=attr-face-readonly data-dfn-type=element-attr><code>readonly</code></dfn> attribute of <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-10>form-associated custom elements</a> specifies that the element is <span>barred
  from constraint validation</span>. User agents don't provide any other behavior for the attribute,
  but custom element authors should, where possible, use its presence to make their control
  non-editable in some appropriate fashion, similar to the behavior for the <a href=input.html#attr-input-readonly id=custom-elements-core-concepts:attr-input-readonly>readonly</a> attribute on built-in form controls.</p>

  <p><strong>Constraint validation</strong>: If the <code id=custom-elements-core-concepts:attr-face-readonly-2><a href=#attr-face-readonly>readonly</a></code> attribute is specified on a <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-11>form-associated
  custom element</a>, the element is <span>barred from constraint validation</span>.</p>

  <p>The <span>reset algorithm</span> for <a href=#form-associated-custom-element id=custom-elements-core-concepts:form-associated-custom-element-12>form-associated custom elements</a> is to <span>enqueue
  a custom element callback reaction</span> with the element, callback name "<code>formResetCallback</code>", and « ».</p>

  <hr>

  <p>A string <var>name</var> is a <dfn id=valid-custom-element-name data-export="">valid custom element name</dfn> if all of the
  following are true:</p>

  <ul><li>
    <p><var>name</var> is a <a id=custom-elements-core-concepts:valid-element-local-name href=https://dom.spec.whatwg.org/#valid-element-local-name data-x-internal=valid-element-local-name>valid element local name</a>;</p>

    <p class=note>This ensures the custom element can be created with <code id=custom-elements-core-concepts:dom-document-createelement><a data-x-internal=dom-document-createelement href=https://dom.spec.whatwg.org/#dom-document-createelement>createElement()</a></code>.</p>
   <li>
    <p><var>name</var>'s 0th <a id=custom-elements-core-concepts:code-point href=https://infra.spec.whatwg.org/#code-point data-x-internal=code-point>code point</a> is an <a id=custom-elements-core-concepts:lowercase-ascii-letters href=https://infra.spec.whatwg.org/#ascii-lower-alpha data-x-internal=lowercase-ascii-letters>ASCII lower alpha</a>;</p>

    <p class=note>This ensures the HTML parser will treat the name as a tag name instead of as
    text.</p>
   <li>
    <p><var>name</var> does not contain any <a href=https://infra.spec.whatwg.org/#ascii-upper-alpha id=custom-elements-core-concepts:uppercase-ascii-letters-2 data-x-internal=uppercase-ascii-letters>ASCII upper
    alphas</a>;</p>

    <p class=note>This ensures the user agent can always treat HTML elements
    ASCII-case-insensitively.</p>
   <li>
    <p><var>name</var> contains a U+002D (-); and</p>

    <p class=note>This is used for namespacing and to ensure forward compatibility (since no
    elements will be added to HTML, SVG, or MathML with hyphen-containing local names going
    forward).</p>
   <li>
    <p><var>name</var> is not one of the following:</p>

    <ul class=brief><li>"<code>annotation-xml</code>"<li>"<code>color-profile</code>"<li>"<code>font-face</code>"<li>"<code>font-face-src</code>"<li>"<code>font-face-uri</code>"<li>"<code>font-face-format</code>"<li>"<code>font-face-name</code>"<li>"<code>missing-glyph</code>"</ul>

    <p class=note>The list of names above is the summary of all hyphen-containing element names
    from the <a href=infrastructure.html#other-applicable-specifications id=custom-elements-core-concepts:other-applicable-specifications>applicable specifications</a>, namely
    <cite>SVG 2</cite> and <cite>MathML</cite>. <a href=references.html#refsSVG>[SVG]</a> <a href=references.html#refsMATHML>[MATHML]</a></p>
   </ul>

  <p>Apart from these restrictions, a large variety of names is allowed, to give maximum
  flexibility for use cases like <code>&lt;math-α></code> or <code>&lt;emotion-😍></code>.</p>

  

  <h4 id=custom-elements-api><span class=secno>4.13.4</span> The <code>CustomElementRegistry</code> interface<a href=#custom-elements-api class=self-link></a></h4><div class="mdn-anno wrapped"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry title="The CustomElementRegistry interface provides methods for registering custom elements and querying registered elements. To get an instance of it, use the window.customElements property.">CustomElementRegistry</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>63+</span></span><span class="safari yes"><span>Safari</span><span>10.1+</span></span><span class="chrome yes"><span>Chrome</span><span>54+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div>

  

  <dl class=domintro><dt><code><var>registry</var> = <var>window</var>.<span id=dom-window-customelements>customElements</span></code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/Window/customElements title="The customElements read-only property of the Window interface returns a reference to the CustomElementRegistry object, which can be used to register new custom elements and get information about previously registered custom elements.">Window/customElements</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>63+</span></span><span class="safari yes"><span>Safari</span><span>10.1+</span></span><span class="chrome yes"><span>Chrome</span><span>54+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div><dd>Returns the global's associated <code>Document</code>'s <code>CustomElementRegistry</code>
   object.<dt><code><var>registry</var> = new <span id=dom-customelementregistry>CustomElementRegistry</span>()</code><dd>Constructs a new <code>CustomElementRegistry</code> object, for scoped usage.<dt><code><var>registry</var>.<span id=dom-customelementregistry-define>define</span>(<var>name</var>,
   <var>constructor</var>)</code><dd>Defines a new <a href=#custom-element id=custom-elements-api:custom-element>custom element</a>, mapping the given name to the given constructor
   as an <a href=#autonomous-custom-element id=custom-elements-api:autonomous-custom-element>autonomous custom element</a>.<dt><code><var>registry</var>.<a href=#dom-customelementregistry-define id=custom-elements-api:dom-customelementregistry-define>define</a>(<var>name</var>, <var>constructor</var>,
   { extends: <var>baseLocalName</var> })</code><dd>Defines a new <a href=#custom-element id=custom-elements-api:custom-element-2>custom element</a>, mapping the given name to the given constructor as
   a <a href=#customized-built-in-element id=custom-elements-api:customized-built-in-element>customized built-in element</a> for the <a id=custom-elements-api:element-type href=infrastructure.html#element-type>element type</a> identified by the
   supplied <var>baseLocalName</var>. A <a id=custom-elements-api:notsupportederror href=https://webidl.spec.whatwg.org/#notsupportederror data-x-internal=notsupportederror>"<code>NotSupportedError</code>"</a>
   <code id=custom-elements-api:domexception><a data-x-internal=domexception href=https://webidl.spec.whatwg.org/#dfn-DOMException>DOMException</a></code> will be thrown upon trying to extend a <a href=#custom-element id=custom-elements-api:custom-element-3>custom element</a> or
   an unknown element, or when <var>registry</var> is not a global
   <code>CustomElementRegistry</code> object.<dt><code><var>registry</var>.<span id=dom-customelementregistry-get>get</span>(<var>name</var>)</code><dd>Retrieves the <a href=#custom-element-constructor id=custom-elements-api:custom-element-constructor>custom element constructor</a> defined for the given <span>name</span>. Returns undefined if there is no
   <span>custom element definition</span> with the given <span>name</span>.<dt><code><var>registry</var>.<span id=dom-customelementregistry-getname>getName</span>(<var>constructor</var>)</code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/getName title="The getName() method of the CustomElementRegistry interface returns the name for a previously-defined custom element.">CustomElementRegistry/getName</a><div class=support><span class="firefox yes"><span>Firefox</span><span>116+</span></span><span class="safari yes"><span>Safari</span><span title="Partial implementation.">🔰 preview+</span></span><span class="chrome yes"><span>Chrome</span><span>117+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>117+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div><dd>Retrieves the given name for a <a href=#custom-element id=custom-elements-api:custom-element-4>custom element</a> defined for the given <span>constructor</span>. Returns null if there is no
   <span>custom element definition</span> with the given <span>constructor</span>.<dt><code><var>registry</var>.<span id=dom-customelementregistry-whendefined>whenDefined</span>(<var>name</var>)</code><dd>Returns a promise that will be fulfilled with the <a href=#custom-element id=custom-elements-api:custom-element-5>custom element</a>'s constructor
   when a <a href=#custom-element id=custom-elements-api:custom-element-6>custom element</a> becomes defined with the given name. (If such a <a href=#custom-element id=custom-elements-api:custom-element-7>custom
   element</a> is already defined, the returned promise will be immediately fulfilled.) Returns a
   promise rejected with a <a id=custom-elements-api:syntaxerror href=https://webidl.spec.whatwg.org/#syntaxerror data-x-internal=syntaxerror>"<code>SyntaxError</code>"</a> <code id=custom-elements-api:domexception-2><a data-x-internal=domexception href=https://webidl.spec.whatwg.org/#dfn-DOMException>DOMException</a></code> if not
   given a <a href=#valid-custom-element-name id=custom-elements-api:valid-custom-element-name>valid custom element name</a>.<dt><code><var>registry</var>.<span id=dom-customelementregistry-upgrade>upgrade</span>(<var>root</var>)</code><dd><span>Tries to upgrade</span> all <a id=custom-elements-api:shadow-including-inclusive-descendant href=https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant data-x-internal=shadow-including-inclusive-descendant>shadow-including
   inclusive descendant</a> elements of <var>root</var>, even if they are not
   <a id=custom-elements-api:connected href=https://dom.spec.whatwg.org/#connected data-x-internal=connected>connected</a>.<dt><code><var>registry</var>.<span id=dom-customelementregistry-initialize>initialize</span>(<var>root</var>)</code><dd>Each <a id=custom-elements-api:inclusive-descendant href=https://dom.spec.whatwg.org/#concept-tree-inclusive-descendant data-x-internal=inclusive-descendant>inclusive descendant</a> of <var>root</var> with a null registry will have it
   updated to this <code>CustomElementRegistry</code> object. A
   <a id=custom-elements-api:notsupportederror-2 href=https://webidl.spec.whatwg.org/#notsupportederror data-x-internal=notsupportederror>"<code>NotSupportedError</code>"</a> <code id=custom-elements-api:domexception-3><a data-x-internal=domexception href=https://webidl.spec.whatwg.org/#dfn-DOMException>DOMException</a></code> will be thrown if this
   <code>CustomElementRegistry</code> object is not for scoped usage and either <var>root</var> is a
   <code>Document</code> node or <var>root</var>'s <a id=custom-elements-api:node-document href=https://dom.spec.whatwg.org/#concept-node-document data-x-internal=node-document>node document</a>'s <a href=https://dom.spec.whatwg.org/#document-custom-element-registry id=custom-elements-api:document-custom-element-registry data-x-internal=document-custom-element-registry>custom element registry</a> is not this
   <code>CustomElementRegistry</code> object.</dl>

  

  <p><dfn id=element-definition>Element definition</dfn> is a process of adding a <span>custom element definition</span>
  to the <code>CustomElementRegistry</code>. This is accomplished by the <code id=custom-elements-api:dom-customelementregistry-define-2><a href=#dom-customelementregistry-define>define()</a></code> method.</p>

  

  <div class=example>
   <p>The <code id=custom-elements-api:dom-customelementregistry-whendefined><a href=#dom-customelementregistry-whendefined>whenDefined()</a></code> method can be
   used to avoid performing an action until all appropriate <a href=#custom-element id=custom-elements-api:custom-element-8>custom
   elements</a> are <a href=https://dom.spec.whatwg.org/#concept-element-defined id=custom-elements-api:concept-element-defined data-x-internal=concept-element-defined>defined</a>. In this example, we
   combine it with the <code>:defined</code> pseudo-class to hide a
   dynamically-loaded article's contents until we're sure that all of the <a href=#autonomous-custom-element id=custom-elements-api:autonomous-custom-element-2>autonomous custom elements</a> it uses are defined.</p>

   <pre><code class='js'>articleContainer<c- p>.</c->hidden <c- o>=</c-> <c- kc>true</c-><c- p>;</c->

fetch<c- p>(</c->articleURL<c- p>)</c->
  <c- p>.</c->then<c- p>(</c->response <c- p>=&gt;</c-> response<c- p>.</c->text<c- p>())</c->
  <c- p>.</c->then<c- p>(</c->text <c- p>=&gt;</c-> <c- p>{</c->
    articleContainer<c- p>.</c->innerHTML <c- o>=</c-> text<c- p>;</c->

    <c- k>return</c-> Promise<c- p>.</c->all<c- p>(</c->
      <c- p>[...</c->articleContainer<c- p>.</c->querySelectorAll<c- p>(</c-><c- u>&quot;:not(:defined)&quot;</c-><c- p>)]</c->
        <c- p>.</c->map<c- p>(</c->el <c- p>=&gt;</c-> customElements<c- p>.</c->whenDefined<c- p>(</c->el<c- p>.</c->localName<c- p>))</c->
    <c- p>);</c->
  <c- p>})</c->
  <c- p>.</c->then<c- p>(()</c-> <c- p>=&gt;</c-> <c- p>{</c->
    articleContainer<c- p>.</c->hidden <c- o>=</c-> <c- kc>false</c-><c- p>;</c->
  <c- p>});</c-></code></pre>
  </div>

  

  <div class=example>
   <p>The <code id=custom-elements-api:dom-customelementregistry-upgrade><a href=#dom-customelementregistry-upgrade>upgrade()</a></code> method allows upgrading
   of elements at will. Normally elements are automatically upgraded when they become
   <a id=custom-elements-api:connected-2 href=https://dom.spec.whatwg.org/#connected data-x-internal=connected>connected</a>, but this method can be used if you need to upgrade before you're ready to
   connect the element.</p>

   <pre><code class='js'><c- a>const</c-> el <c- o>=</c-> document<c- p>.</c->createElement<c- p>(</c-><c- u>&quot;spider-man&quot;</c-><c- p>);</c->

<c- a>class</c-> SpiderMan <c- k>extends</c-> HTMLElement <c- p>{}</c->
customElements<c- p>.</c->define<c- p>(</c-><c- u>&quot;spider-man&quot;</c-><c- p>,</c-> SpiderMan<c- p>);</c->

console<c- p>.</c->assert<c- p>(</c-><c- o>!</c-><c- p>(</c->el <c- k>instanceof</c-> SpiderMan<c- p>));</c-> <c- c1>// not yet upgraded</c->

customElements<c- p>.</c->upgrade<c- p>(</c->el<c- p>);</c->
console<c- p>.</c->assert<c- p>(</c->el <c- k>instanceof</c-> SpiderMan<c- p>);</c->    <c- c1>// upgraded!</c-></code></pre>
  </div>

  

  <h4 id=custom-element-reactions><span class=secno>4.13.5</span> Custom element reactions<a href=#custom-element-reactions class=self-link></a></h4>

  <p>A <a href=#custom-element id=custom-element-reactions:custom-element>custom element</a> possesses the ability to respond to certain occurrences by
  running author code:</p>

  <ul><li><p>When <span>upgraded</span>, its <a href=#custom-element-constructor id=custom-element-reactions:custom-element-constructor>constructor</a> is run, with no arguments.<li><p>When it <a id=custom-element-reactions:becomes-connected href=infrastructure.html#becomes-connected>becomes connected</a>, its <code>connectedCallback</code> is
   called, with no arguments.<li><p>When it <a id=custom-element-reactions:becomes-disconnected href=infrastructure.html#becomes-disconnected>becomes disconnected</a>, its <code>disconnectedCallback</code>
   is called, with no arguments.<li><p>When it is <a href=https://dom.spec.whatwg.org/#concept-node-move-ext id=custom-element-reactions:concept-node-move-ext data-x-internal=concept-node-move-ext>moved</a>, its <code>connectedMoveCallback</code> is called, with no arguments.<li><p>When it is <a href=https://dom.spec.whatwg.org/#concept-node-adopt id=custom-element-reactions:concept-node-adopt data-x-internal=concept-node-adopt>adopted</a> into a new document, its <code>adoptedCallback</code> is called, given the old document and new document as
   arguments.<li><p>When any of its attributes are <a href=https://dom.spec.whatwg.org/#concept-element-attributes-change id=custom-element-reactions:concept-element-attributes-change data-x-internal=concept-element-attributes-change>changed</a>, <a href=https://dom.spec.whatwg.org/#concept-element-attributes-append id=custom-element-reactions:concept-element-attributes-append data-x-internal=concept-element-attributes-append>appended</a>, <a href=https://dom.spec.whatwg.org/#concept-element-attributes-remove id=custom-element-reactions:concept-element-attributes-remove data-x-internal=concept-element-attributes-remove>removed</a>, or <a href=https://dom.spec.whatwg.org/#concept-element-attributes-replace id=custom-element-reactions:concept-element-attributes-replace data-x-internal=concept-element-attributes-replace>replaced</a>, its <code>attributeChangedCallback</code> is called, given the attribute's local name, old value,
   new value, and namespace as arguments. (An attribute's old or new value is considered to be null
   when the attribute is added or removed, respectively.)<li><p>When the user agent <span>resets the form owner</span> of a
   <a href=#form-associated-custom-element id=custom-element-reactions:form-associated-custom-element>form-associated custom element</a> and doing so changes the form owner, its <code>formAssociatedCallback</code> is called, given the new form owner (or null if no owner)
   as an argument.<li><p>When the form owner of a <a href=#form-associated-custom-element id=custom-element-reactions:form-associated-custom-element-2>form-associated custom element</a> is <span>reset</span>, its <code>formResetCallback</code> is
   called.<li><p>When the <a href=form-control-infrastructure.html#concept-fe-disabled id=custom-element-reactions:concept-fe-disabled>disabled</a> state of a
   <a href=#form-associated-custom-element id=custom-element-reactions:form-associated-custom-element-3>form-associated custom element</a> is changed, its <code>formDisabledCallback</code> is called, given the new state as an
   argument.<li><p>When the user agent updates a <a href=#form-associated-custom-element id=custom-element-reactions:form-associated-custom-element-4>form-associated custom element</a>'s value on behalf of
   a user or <a href=browsing-the-web.html#restore-persisted-state id=custom-element-reactions:restore-persisted-state>as part of navigation</a>, its <code>formStateRestoreCallback</code> is called, given the new state and a string indicating
   a reason, "<code>autocomplete</code>" or "<code>restore</code>", as
   arguments.</ul>

  <p>We call these reactions collectively <dfn id=concept-custom-element-reaction>custom
  element reactions</dfn>.</p>

  <p>The way in which <a href=#concept-custom-element-reaction id=custom-element-reactions:concept-custom-element-reaction>custom element reactions</a>
  are invoked is done with special care, to avoid running author code during the middle of delicate
  operations. Effectively, they are delayed until "just before returning to user script". This means
  that for most purposes they appear to execute synchronously, but in the case of complicated
  composite operations (like <a href=https://dom.spec.whatwg.org/#concept-node-clone id=custom-element-reactions:concept-node-clone data-x-internal=concept-node-clone>cloning</a>, or <a href=https://dom.spec.whatwg.org/#concept-range id=custom-element-reactions:concept-range data-x-internal=concept-range>range</a> manipulation), they will instead be delayed until after all
  the relevant user agent processing steps have completed, and then run together as a batch.</p>

  <p><span>It is guaranteed</span> that <a href=#concept-custom-element-reaction id=custom-element-reactions:concept-custom-element-reaction-2>custom element reactions</a> always are invoked in the
  same order as their triggering actions, at least within the local context of a single <a href=#custom-element id=custom-element-reactions:custom-element-2>custom
  element</a>. (Because <a href=#concept-custom-element-reaction id=custom-element-reactions:concept-custom-element-reaction-3>custom element
  reaction</a> code can perform its own mutations, it is not possible to give a global ordering
  guarantee across multiple elements.)</p>

  

  <h4 id=element-internals><span class=secno>4.13.6</span> Element internals<a href=#element-internals class=self-link></a></h4>

  <p>Certain capabilities are meant to be available to a custom element author, but not to a custom
  element consumer. These are provided by the <code id=element-internals:dom-attachinternals><a href=#dom-attachinternals>element.attachInternals()</a></code> method, which returns an instance of
  <code>ElementInternals</code>. The properties and methods of <code>ElementInternals</code> allow
  control over internal features which the user agent provides to all elements.</p>

  <dl class=domintro><dt><code><var>element</var>.<span id=dom-attachinternals>attachInternals()</span></code><div class="mdn-anno wrapped before"><button onclick=toggleStatus(this) class=mdn-anno-btn><b title="Support in all current engines." class=all-engines-flag>✔</b><span>MDN</span></button><div class=feature><p><a href=https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals title="The HTMLElement.attachInternals() method returns an ElementInternals object. This method allows a custom element to participate in HTML forms. The ElementInternals interface provides utilities for working with these elements in the same way you would work with any standard HTML form element, and also exposes the Accessibility Object Model to the element.">HTMLElement/attachInternals</a><p class=all-engines-text>Support in all current engines.<div class=support><span class="firefox yes"><span>Firefox</span><span>93+</span></span><span class="safari yes"><span>Safari</span><span>16.4+</span></span><span class="chrome yes"><span>Chrome</span><span>77+</span></span><hr><span class="opera unknown"><span>Opera</span><span>?</span></span><span class="edge_blink yes"><span>Edge</span><span>79+</span></span><hr><span class="edge unknown"><span>Edge (Legacy)</span><span>?</span></span><span class="ie no"><span>Internet Explorer</span><span>No</span></span><hr><span class="firefox_android unknown"><span>Firefox Android</span><span>?</span></span><span class="safari_ios unknown"><span>Safari iOS</span><span>?</span></span><span class="chrome_android unknown"><span>Chrome Android</span><span>?</span></span><span class="webview_android unknown"><span>WebView Android</span><span>?</span></span><span class="samsunginternet_android unknown"><span>Samsung Internet</span><span>?</span></span><span class="opera_android unknown"><span>Opera Android</span><span>?</span></span></div></div></div><dd><p>Returns an <code>ElementInternals</code> object targeting the <a href=#custom-element id=element-internals:custom-element>custom element</a>
   <var>element</var>. Throws an exception if <var>element</var> is not a <a href=#custom-element id=element-internals:custom-element-2>custom
   element</a>, if the "<code>internals</code>" feature was disabled as part of the
   element definition, or if it is called twice on the same element.</dl>

  

  <h5 id=shadow-root-access><span class=secno>4.13.6.1</span> Shadow root access<a href=#shadow-root-access class=self-link></a></h5>

  <dl class=domintro><dt><code><var>internals</var>.<span>shadowRoot</span></code><dd><p>Returns the <code id=shadow-root-access:shadowroot><a data-x-internal=shadowroot href=https://dom.spec.whatwg.org/#interface-shadowroot>ShadowRoot</a></code> for <var>internals</var>'s <span>target element</span>, if the <span>target
   element</span> is a <a id=shadow-root-access:shadow-host href=https://dom.spec.whatwg.org/#element-shadow-host data-x-internal=shadow-host>shadow host</a>, or null otherwise.</dl>

  

  <h5 id=form-associated-custom-elements><span class=secno>4.13.6.2</span> Form-associated custom elements<a href=#form-associated-custom-elements class=self-link></a></h5>

  <dl class=domintro><dt><code><var>internals</var>.<span>setFormValue</span>(<var>value</var>)</code><dd>
    <p>Sets both the <a href=#face-state id=form-associated-custom-elements:face-state>state</a> and <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value>submission value</a> of <var>internals</var>'s <span>target element</span> to <var>value</var>.</p>

    <p>If <var>value</var> is null, the element won't participate in form submission.</p>
   <dt><code><var>internals</var>.<span>setFormValue</span>(<var>value</var>,
   <var>state</var>)</code><dd>
    <p>Sets the <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-2>submission value</a> of
    <var>internals</var>'s <span>target element</span> to
    <var>value</var>, and its <a href=#face-state id=form-associated-custom-elements:face-state-2>state</a> to <var>state</var>.</p>

    <p>If <var>value</var> is null, the element won't participate in form submission.</p>
   <dt><code><var>internals</var>.<span>form</span></code><dd><p>Returns the <a id=form-associated-custom-elements:form-owner href=form-control-infrastructure.html#form-owner>form owner</a> of <var>internals</var>'s <span>target element</span>.<dt><code><var>internals</var>.<span>setValidity</span>(<var>flags</var>,
   <var>message</var> [, <var>anchor</var> ])</code><dd><p>Marks <var>internals</var>'s <span>target element</span> as
   suffering from the constraints indicated by the <var>flags</var> argument, and sets the element's
   validation message to <var>message</var>. If <var>anchor</var> is specified, the user agent might
   use it to indicate problems with the constraints of <var>internals</var>'s <span>target element</span> when the <a id=form-associated-custom-elements:form-owner-2 href=form-control-infrastructure.html#form-owner>form owner</a> is validated
   interactively or <code>reportValidity()</code> is
   called.<dt><code><var>internals</var>.<span>setValidity</span>({})</code><dd><p>Marks <var>internals</var>'s <span>target element</span> as
   <span>satisfying its constraints</span>.<dt><code><var>internals</var>.<span>willValidate</span></code><dd><p>Returns true if <var>internals</var>'s <span>target
   element</span> will be validated when the form is submitted; false otherwise.<dt><code><var>internals</var>.<span>validity</span></code><dd><p>Returns the <code>ValidityState</code> object for <var>internals</var>'s <span>target element</span>.<dt><code><var>internals</var>.<span>validationMessage</span></code><dd><p>Returns the error message that would be shown to the user if <var>internals</var>'s <span>target element</span> was to be checked for validity.<dt><code><var>valid</var> = <var>internals</var>.<span>checkValidity()</span></code><dd><p>Returns true if <var>internals</var>'s <span>target
   element</span> has no validity problems; false otherwise. Fires an <code id=form-associated-custom-elements:event-invalid><a href=indices.html#event-invalid>invalid</a></code> event at the element in the latter case.<dt><code><var>valid</var> = <var>internals</var>.<span>reportValidity()</span></code><dd><p>Returns true if <var>internals</var>'s <span>target
   element</span> has no validity problems; otherwise, returns false, fires an <code id=form-associated-custom-elements:event-invalid-2><a href=indices.html#event-invalid>invalid</a></code> event at the element, and (if the event isn't canceled)
   reports the problem to the user.<dt><code><var>internals</var>.<span>labels</span></code><dd><p>Returns a <code id=form-associated-custom-elements:nodelist><a data-x-internal=nodelist href=https://dom.spec.whatwg.org/#interface-nodelist>NodeList</a></code> of all the <code id=form-associated-custom-elements:the-label-element><a href=forms.html#the-label-element>label</a></code> elements that
   <var>internals</var>'s <span>target element</span> is associated
   with.</dl>

  <p>Each <a href=#form-associated-custom-element id=form-associated-custom-elements:form-associated-custom-element>form-associated custom element</a> has <dfn id=face-submission-value>submission value</dfn>. It is used to provide one or more
  <span>entries</span> on form submission.
  The initial value of <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-3>submission value</a> is null, and
  <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-4>submission value</a> can be null, a string, a
  <code id=form-associated-custom-elements:file><a data-x-internal=file href=https://w3c.github.io/FileAPI/#dfn-file>File</a></code>, or a <a id=form-associated-custom-elements:list href=https://infra.spec.whatwg.org/#list data-x-internal=list>list</a> of <span>entries</span>.</p>

  <p>Each <a href=#form-associated-custom-element id=form-associated-custom-elements:form-associated-custom-element-2>form-associated custom element</a> has <dfn id=face-state>state</dfn>.
  It is information with which the user agent can restore a user's input for the element.
  The initial value of <a href=#face-state id=form-associated-custom-elements:face-state-3>state</a> is null, and <a href=#face-state id=form-associated-custom-elements:face-state-4>state</a> can be null, a string, a <code id=form-associated-custom-elements:file-2><a data-x-internal=file href=https://w3c.github.io/FileAPI/#dfn-file>File</a></code>, or a
  <a id=form-associated-custom-elements:list-2 href=https://infra.spec.whatwg.org/#list data-x-internal=list>list</a> of <span>entries</span>.</p>

  <p>The <code>setFormValue()</code> method is used by
  the custom element author to set the element's <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-5>submission
  value</a> and <a href=#face-state id=form-associated-custom-elements:face-state-5>state</a>, thus communicating these to the user
  agent.</p>

  <p>When the user agent believes it is a good idea to restore a <a href=#form-associated-custom-element id=form-associated-custom-elements:form-associated-custom-element-3>form-associated custom
  element</a>'s <a href=#face-state id=form-associated-custom-elements:face-state-6>state</a>, for example <a href=browsing-the-web.html#restore-persisted-state id=form-associated-custom-elements:restore-persisted-state>after navigation</a> or restarting the user agent, they may <span>enqueue a
  custom element callback reaction</span> with that element, callback name "<code>formStateRestoreCallback</code>", and « the state to be restored, "<code>restore</code>" ».</p>

  <p>If the user agent has a form-filling assist feature, then when the feature is invoked, it may
  <span>enqueue a custom element callback reaction</span> with a <a href=#form-associated-custom-element id=form-associated-custom-elements:form-associated-custom-element-4>form-associated custom
  element</a>, callback name "<code>formStateRestoreCallback</code>", and « the state
  value determined by history of state value and some heuristics, "<code>autocomplete</code>" ».</p>

  <p>In general, the <a href=#face-state id=form-associated-custom-elements:face-state-7>state</a> is information specified by a user, and
  the <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-6>submission value</a> is a value after canonicalization
  or sanitization, suitable for submission to the server. The following examples makes this
  concrete:</p>

  <p class=example>Suppose that we have a <a href=#form-associated-custom-element id=form-associated-custom-elements:form-associated-custom-element-5>form-associated custom element</a> which asks a
  user to specify a date. The user specifies <kbd>"3/15/2019"</kbd>, but the control wishes to
  submit <code>"2019-03-15"</code> to the server. <kbd>"3/15/2019"</kbd> would be a <a href=#face-state id=form-associated-custom-elements:face-state-8>state</a> of the element, and <code>"2019-03-15"</code> would be
  a <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-7>submission value</a>.</p>

  <p class=example>Suppose you develop a custom element emulating a the behavior of the existing
  <a href="input.html#checkbox-state-(type=checkbox)" id="form-associated-custom-elements:checkbox-state-(type=checkbox)">checkbox</a> <code id=form-associated-custom-elements:the-input-element><a href=input.html#the-input-element>input</a></code> type. Its <a href=#face-submission-value id=form-associated-custom-elements:face-submission-value-8>submission value</a> would be the value of its <code>value</code> content attribute, or the string <code>"on"</code>. Its <a href=#face-state id=form-associated-custom-elements:face-state-9>state</a> would be one of <code>"checked"</code>, <code>"unchecked"</code>, <code>"checked/indeterminate"</code>, or <code>"unchecked/indeterminate"</code>.</p>

  

  <h5 id=accessibility-semantics><span class=secno>4.13.6.3</span> Accessibility semantics<a href=#accessibility-semantics class=self-link></a></h5>

  <dl class=domintro><dt><code><var>internals</var>.<a href=https://w3c.github.io/aria/#idl-def-ariamixin-role id=accessibility-semantics:dom-ariamixin-role data-x-internal=dom-ariamixin-role>role</a> [ = <var>value</var> ]</code><dd><p>Sets or retrieves the default ARIA role for <var>internals</var>'s <span>target element</span>, which will be used unless the page author
   overrides it using the <code id=accessibility-semantics:attr-aria-role><a href=infrastructure.html#attr-aria-role>role</a></code> attribute.<dt><code><var>internals</var>.<a href=https://w3c.github.io/aria/#idl-def-ariamixin-ariaactivedescendantelement id=accessibility-semantics:dom-ariamixin-aria* data-x-internal=dom-ariamixin-aria*>aria*</a> [ = <var>value</var> ]</code><dd><p>Sets or retrieves various default ARIA states or property values for
   <var>internals</var>'s <span>target element</span>, which will be used
   unless the page author overrides them using the <code id=accessibility-semantics:attr-aria-*><a href=infrastructure.html#attr-aria-*>aria-*</a></code>
   attributes.</dl>

  <p>By using the <code>role</code> and <code>aria*</code> properties of
  <code>ElementInternals</code>, custom element authors can set default accessibile roles, states,
  and property values for their custom element, similar to how native elements behave. See <a href=#custom-elements-accessibility-example>the example above</a> for more details.</p>

  

  <h5 id=custom-state-pseudo-class><span class=secno>4.13.6.4</span> Custom state pseudo-class<a href=#custom-state-pseudo-class class=self-link></a></h5>

  <dl class=domintro><dt><code><var>internals</var>.<span>states</span>.add(<var>value</var>)</code><dd>
    <p>Adds the string <var>value</var> to the element's <span>states set</span> to be exposed as a
    pseudo-class.</p>
   <dt><code><var>internals</var>.<span>states</span>.has(<var>value</var>)</code><dd>
    <p>Returns true if <var>value</var> is in the element's <span>states set</span>, otherwise
    false.</p>
   <dt><code><var>internals</var>.<span>states</span>.delete(<var>value</var>)</code><dd>
    <p>If the element's <span>states set</span> has <var>value</var>, then it will be removed and
    true will be returned. Otherwise, false will be returned.</p>
   <dt><code><var>internals</var>.<span>states</span>.clear()</code><dd>
    <p>Removes all values from the element's <span>states set</span>.</p>
   <dt><code>for (const <var>stateName</var> of <var>internals</var>.<span>states</span>)</code><dt><code>for (const <var>stateName</var> of <var>internals</var>.<span>states</span>.entries())</code><dt><code>for (const <var>stateName</var> of <var>internals</var>.<span>states</span>.keys())</code><dt><code>for (const <var>stateName</var> of <var>internals</var>.<span>states</span>.values())</code><dd>
    <p>Iterates over all values in the element's <span>states set</span>.</p>
   <dt><code><var>internals</var>.<span>states</span>.forEach(<var>callback</var>)</code><dd>
    <p>Iterates over all values in the element's <span>states set</span> by calling
    <var>callback</var> once for each value.</p>
   <dt><code><var>internals</var>.<span>states</span>.size</code><dd>
    <p>Returns the number of values in the element's <span>states set</span>.</p>
   </dl>

  

  <div class=example>
   <p>The <span>states set</span> can expose boolean states represented by existence/non-existence
   of string values. If an author wants to expose a state which can have three values, it can be
   converted to three exclusive boolean states. For example, a state called <code>readyState</code> with <code>"loading"</code>, <code>"interactive"</code>, and <code>"complete"</code> values can be mapped to
   three exclusive boolean states, <code>"loading"</code>, <code>"interactive"</code>, and <code>"complete"</code>:</p>

   <pre><code class='js'><c- c1>// Change the readyState from anything to &quot;complete&quot;.</c->
<c- k>this</c-><c- p>.</c->_readyState <c- o>=</c-> <c- u>&quot;complete&quot;</c-><c- p>;</c->
<c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c-><c- k>delete</c-><c- p>(</c-><c- u>&quot;loading&quot;</c-><c- p>);</c->
<c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c-><c- k>delete</c-><c- p>(</c-><c- u>&quot;interactive&quot;</c-><c- p>);</c->
<c- k>this</c-><c- p>.</c->_internals<c- p>.</c->states<c- p>.</c->add<c- p>(</c-><c- u>&quot;complete&quot;</c-><c- p>);</c-></code></pre>
  </div>

  <nav><a href=canvas.html>← 4.12.5 The canvas element</a> — <a href=index.html>Table of Contents</a> — <a href=semantics-other.html>4.14 Common idioms without dedicated elements →</a></nav>
